openlogic-couchrest_model 1.0.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/.gitignore +11 -0
- data/.rspec +4 -0
- data/Gemfile +4 -0
- data/LICENSE +176 -0
- data/README.md +137 -0
- data/Rakefile +38 -0
- data/THANKS.md +21 -0
- data/VERSION +1 -0
- data/benchmarks/dirty.rb +118 -0
- data/couchrest_model.gemspec +36 -0
- data/history.md +309 -0
- data/init.rb +1 -0
- data/lib/couchrest/model.rb +10 -0
- data/lib/couchrest/model/associations.rb +231 -0
- data/lib/couchrest/model/base.rb +129 -0
- data/lib/couchrest/model/callbacks.rb +28 -0
- data/lib/couchrest/model/casted_array.rb +83 -0
- data/lib/couchrest/model/casted_by.rb +33 -0
- data/lib/couchrest/model/casted_hash.rb +84 -0
- data/lib/couchrest/model/class_proxy.rb +135 -0
- data/lib/couchrest/model/collection.rb +273 -0
- data/lib/couchrest/model/configuration.rb +67 -0
- data/lib/couchrest/model/connection.rb +70 -0
- data/lib/couchrest/model/core_extensions/hash.rb +9 -0
- data/lib/couchrest/model/core_extensions/time_parsing.rb +66 -0
- data/lib/couchrest/model/design_doc.rb +128 -0
- data/lib/couchrest/model/designs.rb +91 -0
- data/lib/couchrest/model/designs/view.rb +513 -0
- data/lib/couchrest/model/dirty.rb +39 -0
- data/lib/couchrest/model/document_queries.rb +99 -0
- data/lib/couchrest/model/embeddable.rb +78 -0
- data/lib/couchrest/model/errors.rb +25 -0
- data/lib/couchrest/model/extended_attachments.rb +83 -0
- data/lib/couchrest/model/persistence.rb +178 -0
- data/lib/couchrest/model/properties.rb +228 -0
- data/lib/couchrest/model/property.rb +114 -0
- data/lib/couchrest/model/property_protection.rb +71 -0
- data/lib/couchrest/model/proxyable.rb +183 -0
- data/lib/couchrest/model/support/couchrest_database.rb +13 -0
- data/lib/couchrest/model/support/couchrest_design.rb +33 -0
- data/lib/couchrest/model/typecast.rb +154 -0
- data/lib/couchrest/model/validations.rb +80 -0
- data/lib/couchrest/model/validations/casted_model.rb +16 -0
- data/lib/couchrest/model/validations/locale/en.yml +5 -0
- data/lib/couchrest/model/validations/uniqueness.rb +69 -0
- data/lib/couchrest/model/views.rb +151 -0
- data/lib/couchrest/railtie.rb +24 -0
- data/lib/couchrest_model.rb +66 -0
- data/lib/rails/generators/couchrest_model.rb +16 -0
- data/lib/rails/generators/couchrest_model/config/config_generator.rb +18 -0
- data/lib/rails/generators/couchrest_model/config/templates/couchdb.yml +21 -0
- data/lib/rails/generators/couchrest_model/model/model_generator.rb +27 -0
- data/lib/rails/generators/couchrest_model/model/templates/model.rb +2 -0
- data/spec/.gitignore +1 -0
- data/spec/fixtures/attachments/README +3 -0
- data/spec/fixtures/attachments/couchdb.png +0 -0
- data/spec/fixtures/attachments/test.html +11 -0
- data/spec/fixtures/config/couchdb.yml +10 -0
- data/spec/fixtures/models/article.rb +36 -0
- data/spec/fixtures/models/base.rb +164 -0
- data/spec/fixtures/models/card.rb +19 -0
- data/spec/fixtures/models/cat.rb +23 -0
- data/spec/fixtures/models/client.rb +6 -0
- data/spec/fixtures/models/course.rb +27 -0
- data/spec/fixtures/models/event.rb +8 -0
- data/spec/fixtures/models/invoice.rb +14 -0
- data/spec/fixtures/models/key_chain.rb +5 -0
- data/spec/fixtures/models/membership.rb +4 -0
- data/spec/fixtures/models/person.rb +11 -0
- data/spec/fixtures/models/project.rb +6 -0
- data/spec/fixtures/models/question.rb +7 -0
- data/spec/fixtures/models/sale_entry.rb +9 -0
- data/spec/fixtures/models/sale_invoice.rb +14 -0
- data/spec/fixtures/models/service.rb +10 -0
- data/spec/fixtures/models/user.rb +22 -0
- data/spec/fixtures/views/lib.js +3 -0
- data/spec/fixtures/views/test_view/lib.js +3 -0
- data/spec/fixtures/views/test_view/only-map.js +4 -0
- data/spec/fixtures/views/test_view/test-map.js +3 -0
- data/spec/fixtures/views/test_view/test-reduce.js +3 -0
- data/spec/functional/validations_spec.rb +8 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/unit/active_model_lint_spec.rb +30 -0
- data/spec/unit/assocations_spec.rb +242 -0
- data/spec/unit/attachment_spec.rb +176 -0
- data/spec/unit/base_spec.rb +537 -0
- data/spec/unit/casted_spec.rb +72 -0
- data/spec/unit/class_proxy_spec.rb +167 -0
- data/spec/unit/collection_spec.rb +86 -0
- data/spec/unit/configuration_spec.rb +77 -0
- data/spec/unit/connection_spec.rb +148 -0
- data/spec/unit/core_extensions/time_parsing.rb +77 -0
- data/spec/unit/design_doc_spec.rb +241 -0
- data/spec/unit/designs/view_spec.rb +831 -0
- data/spec/unit/designs_spec.rb +134 -0
- data/spec/unit/dirty_spec.rb +436 -0
- data/spec/unit/embeddable_spec.rb +498 -0
- data/spec/unit/inherited_spec.rb +33 -0
- data/spec/unit/persistence_spec.rb +481 -0
- data/spec/unit/property_protection_spec.rb +192 -0
- data/spec/unit/property_spec.rb +481 -0
- data/spec/unit/proxyable_spec.rb +376 -0
- data/spec/unit/subclass_spec.rb +85 -0
- data/spec/unit/typecast_spec.rb +521 -0
- data/spec/unit/validations_spec.rb +140 -0
- data/spec/unit/view_spec.rb +367 -0
- metadata +301 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
class DummyProxyable < CouchRest::Model::Base
|
|
4
|
+
proxy_database_method :db
|
|
5
|
+
def db
|
|
6
|
+
'db'
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class ProxyKitten < CouchRest::Model::Base
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe CouchRest::Model::Proxyable do
|
|
14
|
+
|
|
15
|
+
describe "#proxy_database" do
|
|
16
|
+
|
|
17
|
+
before do
|
|
18
|
+
@class = Class.new(CouchRest::Model::Base)
|
|
19
|
+
@class.class_eval do
|
|
20
|
+
def slug; 'proxy'; end
|
|
21
|
+
end
|
|
22
|
+
@obj = @class.new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should respond to method" do
|
|
26
|
+
@obj.should respond_to(:proxy_database)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should provide proxy database from method" do
|
|
30
|
+
@class.stub!(:proxy_database_method).twice.and_return(:slug)
|
|
31
|
+
@obj.proxy_database.should be_a(CouchRest::Database)
|
|
32
|
+
@obj.proxy_database.name.should eql('couchrest_proxy')
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should raise an error if called and no proxy_database_method set" do
|
|
36
|
+
lambda { @obj.proxy_database }.should raise_error(StandardError, /Please set/)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "class methods" do
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
describe ".proxy_owner_method" do
|
|
45
|
+
before(:each) do
|
|
46
|
+
@class = DummyProxyable.clone
|
|
47
|
+
end
|
|
48
|
+
it "should provide proxy_owner_method accessors" do
|
|
49
|
+
@class.should respond_to(:proxy_owner_method)
|
|
50
|
+
@class.should respond_to(:proxy_owner_method=)
|
|
51
|
+
end
|
|
52
|
+
it "should work as expected" do
|
|
53
|
+
@class.proxy_owner_method = "foo"
|
|
54
|
+
@class.proxy_owner_method.should eql("foo")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe ".proxy_database_method" do
|
|
59
|
+
before do
|
|
60
|
+
@class = Class.new(CouchRest::Model::Base)
|
|
61
|
+
end
|
|
62
|
+
it "should be possible to set the proxy database method" do
|
|
63
|
+
@class.proxy_database_method :db
|
|
64
|
+
@class.proxy_database_method.should eql(:db)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe ".proxy_for" do
|
|
69
|
+
before(:each) do
|
|
70
|
+
@class = DummyProxyable.clone
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should be provided" do
|
|
74
|
+
@class.should respond_to(:proxy_for)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "should create a new method" do
|
|
78
|
+
DummyProxyable.stub!(:method_defined?).and_return(true)
|
|
79
|
+
DummyProxyable.proxy_for(:cats)
|
|
80
|
+
DummyProxyable.new.should respond_to(:cats)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
describe "generated method" do
|
|
84
|
+
it "should call ModelProxy" do
|
|
85
|
+
DummyProxyable.proxy_for(:cats)
|
|
86
|
+
@obj = DummyProxyable.new
|
|
87
|
+
CouchRest::Model::Proxyable::ModelProxy.should_receive(:new).with(Cat, @obj, 'dummy_proxyable', 'db').and_return(true)
|
|
88
|
+
@obj.should_receive(:proxy_database).and_return('db')
|
|
89
|
+
@obj.cats
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "should call class on root namespace" do
|
|
93
|
+
class ::Document < CouchRest::Model::Base
|
|
94
|
+
def self.foo; puts 'bar'; end
|
|
95
|
+
end
|
|
96
|
+
DummyProxyable.proxy_for(:documents)
|
|
97
|
+
@obj = DummyProxyable.new
|
|
98
|
+
CouchRest::Model::Proxyable::ModelProxy.should_receive(:new).with(::Document, @obj, 'dummy_proxyable', 'db').and_return(true)
|
|
99
|
+
@obj.should_receive('proxy_database').and_return('db')
|
|
100
|
+
@obj.documents
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
describe ".proxied_by" do
|
|
106
|
+
before do
|
|
107
|
+
@class = Class.new(CouchRest::Model::Base)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "should be provided" do
|
|
111
|
+
@class.should respond_to(:proxied_by)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "should add an attribute accessor" do
|
|
115
|
+
@class.proxied_by(:foobar)
|
|
116
|
+
@class.new.should respond_to(:foobar)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "should provide #model_proxy method" do
|
|
120
|
+
@class.proxied_by(:foobar)
|
|
121
|
+
@class.new.should respond_to(:model_proxy)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "should set the proxy_owner_method" do
|
|
125
|
+
@class.proxied_by(:foobar)
|
|
126
|
+
@class.proxy_owner_method.should eql(:foobar)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "should raise an error if model name pre-defined" do
|
|
130
|
+
lambda { @class.proxied_by(:object_id) }.should raise_error
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "should raise an error if object already has a proxy" do
|
|
134
|
+
@class.proxied_by(:department)
|
|
135
|
+
lambda { @class.proxied_by(:company) }.should raise_error
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "should overwrite the database method to provide an error" do
|
|
139
|
+
@class.proxied_by(:company)
|
|
140
|
+
lambda { @class.database }.should raise_error(StandardError, /database must be accessed via/)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
describe "ModelProxy" do
|
|
146
|
+
|
|
147
|
+
before :all do
|
|
148
|
+
@klass = CouchRest::Model::Proxyable::ModelProxy
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "should initialize and set variables" do
|
|
152
|
+
@obj = @klass.new(Cat, 'owner', 'owner_name', 'database')
|
|
153
|
+
@obj.model.should eql(Cat)
|
|
154
|
+
@obj.owner.should eql('owner')
|
|
155
|
+
@obj.owner_name.should eql('owner_name')
|
|
156
|
+
@obj.database.should eql('database')
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
describe "instance" do
|
|
160
|
+
|
|
161
|
+
before :each do
|
|
162
|
+
@obj = @klass.new(Cat, 'owner', 'owner_name', 'database')
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "should proxy new call" do
|
|
166
|
+
@obj.should_receive(:proxy_block_update).with(:new, 'attrs', 'opts')
|
|
167
|
+
@obj.new('attrs', 'opts')
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it "should proxy build_from_database" do
|
|
171
|
+
@obj.should_receive(:proxy_block_update).with(:build_from_database, 'attrs', 'opts')
|
|
172
|
+
@obj.build_from_database('attrs', 'opts')
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
describe "#method_missing" do
|
|
176
|
+
it "should return design view object" do
|
|
177
|
+
m = "by_some_property"
|
|
178
|
+
inst = mock('DesignView')
|
|
179
|
+
inst.stub!(:proxy).and_return(inst)
|
|
180
|
+
@obj.should_receive(:has_view?).with(m).and_return(true)
|
|
181
|
+
Cat.should_receive(:respond_to?).with(m).and_return(true)
|
|
182
|
+
Cat.should_receive(:send).with(m).and_return(inst)
|
|
183
|
+
@obj.method_missing(m).should eql(inst)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "should call view if necessary" do
|
|
187
|
+
m = "by_some_property"
|
|
188
|
+
@obj.should_receive(:has_view?).with(m).and_return(true)
|
|
189
|
+
Cat.should_receive(:respond_to?).with(m).and_return(false)
|
|
190
|
+
@obj.should_receive(:view).with(m, {}).and_return('view')
|
|
191
|
+
@obj.method_missing(m).should eql('view')
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it "should provide wrapper for #first_from_view" do
|
|
195
|
+
m = "find_by_some_property"
|
|
196
|
+
view = "by_some_property"
|
|
197
|
+
@obj.should_receive(:has_view?).with(m).and_return(false)
|
|
198
|
+
@obj.should_receive(:has_view?).with(view).and_return(true)
|
|
199
|
+
@obj.should_receive(:first_from_view).with(view).and_return('view')
|
|
200
|
+
@obj.method_missing(m).should eql('view')
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it "should proxy #all" do
|
|
206
|
+
Cat.should_receive(:all).with({:database => 'database'})
|
|
207
|
+
@obj.should_receive(:proxy_update_all)
|
|
208
|
+
@obj.all
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it "should proxy #count" do
|
|
212
|
+
Cat.should_receive(:all).with({:database => 'database', :raw => true, :limit => 0}).and_return({'total_rows' => 3})
|
|
213
|
+
@obj.count.should eql(3)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it "should proxy #first" do
|
|
217
|
+
Cat.should_receive(:first).with({:database => 'database'})
|
|
218
|
+
@obj.should_receive(:proxy_update)
|
|
219
|
+
@obj.first
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
it "should proxy #last" do
|
|
223
|
+
Cat.should_receive(:last).with({:database => 'database'})
|
|
224
|
+
@obj.should_receive(:proxy_update)
|
|
225
|
+
@obj.last
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
it "should proxy #get" do
|
|
229
|
+
Cat.should_receive(:get).with(32, 'database')
|
|
230
|
+
@obj.should_receive(:proxy_update)
|
|
231
|
+
@obj.get(32)
|
|
232
|
+
end
|
|
233
|
+
it "should proxy #find" do
|
|
234
|
+
Cat.should_receive(:get).with(32, 'database')
|
|
235
|
+
@obj.should_receive(:proxy_update)
|
|
236
|
+
@obj.find(32)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
it "should proxy #has_view?" do
|
|
240
|
+
Cat.should_receive(:has_view?).with('view').and_return(false)
|
|
241
|
+
@obj.has_view?('view')
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
it "should proxy #view_by" do
|
|
245
|
+
Cat.should_receive(:view_by).with('name').and_return(false)
|
|
246
|
+
@obj.view_by('name')
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
it "should proxy #view" do
|
|
250
|
+
Cat.should_receive(:view).with('view', {:database => 'database'})
|
|
251
|
+
@obj.should_receive(:proxy_update_all)
|
|
252
|
+
@obj.view('view')
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it "should proxy #first_from_view" do
|
|
256
|
+
Cat.should_receive(:first_from_view).with('view', {:database => 'database'})
|
|
257
|
+
@obj.should_receive(:proxy_update)
|
|
258
|
+
@obj.first_from_view('view')
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
it "should proxy design_doc" do
|
|
262
|
+
Cat.should_receive(:design_doc)
|
|
263
|
+
@obj.design_doc
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
describe "#save_design_doc" do
|
|
267
|
+
it "should be proxied without args" do
|
|
268
|
+
Cat.should_receive(:save_design_doc).with('database')
|
|
269
|
+
@obj.save_design_doc
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
it "should be proxied with database arg" do
|
|
273
|
+
Cat.should_receive(:save_design_doc).with('db')
|
|
274
|
+
@obj.save_design_doc('db')
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
### Updating methods
|
|
281
|
+
|
|
282
|
+
describe "#proxy_update" do
|
|
283
|
+
it "should set returned doc fields" do
|
|
284
|
+
doc = mock(:Document)
|
|
285
|
+
doc.should_receive(:is_a?).with(Cat).and_return(true)
|
|
286
|
+
doc.should_receive(:database=).with('database')
|
|
287
|
+
doc.should_receive(:model_proxy=).with(@obj)
|
|
288
|
+
doc.should_receive(:send).with('owner_name=', 'owner')
|
|
289
|
+
@obj.send(:proxy_update, doc).should eql(doc)
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
it "should not set anything if matching document not provided" do
|
|
293
|
+
doc = mock(:DocumentFoo)
|
|
294
|
+
doc.should_receive(:is_a?).with(Cat).and_return(false)
|
|
295
|
+
doc.should_not_receive(:database=)
|
|
296
|
+
doc.should_not_receive(:model_proxy=)
|
|
297
|
+
doc.should_not_receive(:owner_name=)
|
|
298
|
+
@obj.send(:proxy_update, doc).should eql(doc)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
it "should pass nil straight through without errors" do
|
|
302
|
+
lambda { @obj.send(:proxy_update, nil).should eql(nil) }.should_not raise_error
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
it "#proxy_update_all should update array of docs" do
|
|
307
|
+
docs = [{}, {}]
|
|
308
|
+
@obj.should_receive(:proxy_update).twice.with({})
|
|
309
|
+
@obj.send(:proxy_update_all, docs)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
describe "#proxy_block_update" do
|
|
313
|
+
it "should proxy block updates" do
|
|
314
|
+
doc = { }
|
|
315
|
+
@obj.model.should_receive(:new).and_yield(doc)
|
|
316
|
+
@obj.should_receive(:proxy_update).with(doc)
|
|
317
|
+
@obj.send(:proxy_block_update, :new)
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
describe "scenarios" do
|
|
326
|
+
|
|
327
|
+
before :all do
|
|
328
|
+
class ProxyableCompany < CouchRest::Model::Base
|
|
329
|
+
use_database DB
|
|
330
|
+
property :slug
|
|
331
|
+
proxy_for :proxyable_invoices
|
|
332
|
+
def proxy_database
|
|
333
|
+
@db ||= TEST_SERVER.database!(TESTDB + "-#{slug}")
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
class ProxyableInvoice < CouchRest::Model::Base
|
|
338
|
+
property :client
|
|
339
|
+
property :total
|
|
340
|
+
proxied_by :proxyable_company
|
|
341
|
+
validates_uniqueness_of :client
|
|
342
|
+
design do
|
|
343
|
+
view :by_total
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
@company = ProxyableCompany.create(:slug => 'samco')
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
it "should create the new database" do
|
|
352
|
+
@company.proxyable_invoices.all.should be_empty
|
|
353
|
+
TEST_SERVER.databases.find{|db| db =~ /#{TESTDB}-samco/}.should_not be_nil
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
it "should allow creation of new entries" do
|
|
357
|
+
inv = @company.proxyable_invoices.new(:client => "Lorena", :total => 35)
|
|
358
|
+
# inv.database.should_not be_nil
|
|
359
|
+
inv.save.should be_true
|
|
360
|
+
@company.proxyable_invoices.count.should eql(1)
|
|
361
|
+
@company.proxyable_invoices.first.client.should eql("Lorena")
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
it "should validate uniqueness" do
|
|
365
|
+
inv = @company.proxyable_invoices.new(:client => "Lorena", :total => 40)
|
|
366
|
+
inv.save.should be_false
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
it "should allow design views" do
|
|
370
|
+
item = @company.proxyable_invoices.by_total.key(35).first
|
|
371
|
+
item.client.should eql('Lorena')
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
# add a default value
|
|
4
|
+
Card.property :bg_color, :default => '#ccc'
|
|
5
|
+
|
|
6
|
+
class BusinessCard < Card
|
|
7
|
+
property :extension_code
|
|
8
|
+
property :job_title
|
|
9
|
+
|
|
10
|
+
validates_presence_of :extension_code
|
|
11
|
+
validates_presence_of :job_title
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class DesignBusinessCard < BusinessCard
|
|
15
|
+
property :bg_color, :default => '#eee'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class OnlineCourse < Course
|
|
19
|
+
property :url
|
|
20
|
+
view_by :url
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class Animal < CouchRest::Model::Base
|
|
24
|
+
use_database TEST_SERVER.default_database
|
|
25
|
+
property :name
|
|
26
|
+
view_by :name
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class Dog < Animal; end
|
|
30
|
+
|
|
31
|
+
describe "Subclassing a Model" do
|
|
32
|
+
|
|
33
|
+
before(:each) do
|
|
34
|
+
@card = BusinessCard.new
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "shouldn't messup the parent's properties" do
|
|
38
|
+
Card.properties.should_not == BusinessCard.properties
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should share the same db default" do
|
|
42
|
+
@card.database.uri.should == Card.database.uri
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should have kept the validation details" do
|
|
46
|
+
@card.should_not be_valid
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should have added the new validation details" do
|
|
50
|
+
validated_fields = @card.class.validators.map{|v| v.attributes}.flatten
|
|
51
|
+
validated_fields.should include(:extension_code)
|
|
52
|
+
validated_fields.should include(:job_title)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should not add to the parent's validations" do
|
|
56
|
+
validated_fields = Card.validators.map{|v| v.attributes}.flatten
|
|
57
|
+
validated_fields.should_not include(:extension_code)
|
|
58
|
+
validated_fields.should_not include(:job_title)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "should inherit default property values" do
|
|
62
|
+
@card.bg_color.should == '#ccc'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should be able to overwrite a default property" do
|
|
66
|
+
DesignBusinessCard.new.bg_color.should == '#eee'
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should have a design doc slug based on the subclass name" do
|
|
70
|
+
OnlineCourse.design_doc_slug.should =~ /^OnlineCourse/
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should not add views to the parent's design_doc" do
|
|
74
|
+
Course.design_doc['views'].keys.should_not include('by_url')
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "should not add the parent's views to its design doc" do
|
|
78
|
+
OnlineCourse.design_doc['views'].keys.should_not include('by_title')
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "should have an all view with a guard clause for model == subclass name in the map function" do
|
|
82
|
+
OnlineCourse.design_doc['views']['all']['map'].should =~ /if \(doc\['#{OnlineCourse.model_type_key}'\] == 'OnlineCourse'\)/
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|