couchrest_model 1.0.0.beta8 → 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 +9 -0
- data/{spec/spec.opts → .rspec} +0 -1
- data/Gemfile +4 -0
- data/Gemfile.lock +77 -0
- data/README.md +144 -57
- data/Rakefile +12 -43
- data/VERSION +1 -0
- data/couchrest_model.gemspec +35 -0
- data/history.txt +23 -1
- data/init.rb +1 -0
- data/lib/couchrest/model/associations.rb +17 -1
- data/lib/couchrest/model/base.rb +5 -5
- data/lib/couchrest/model/casted_model.rb +2 -2
- data/lib/couchrest/model/class_proxy.rb +6 -0
- data/lib/couchrest/model/collection.rb +3 -0
- data/lib/couchrest/model/configuration.rb +51 -0
- data/lib/couchrest/model/design_doc.rb +2 -5
- data/lib/couchrest/model/document_queries.rb +20 -3
- data/lib/couchrest/model/persistence.rb +15 -1
- data/lib/couchrest/model/properties.rb +97 -23
- data/lib/couchrest/model/property.rb +5 -4
- data/lib/couchrest/model/property_protection.rb +71 -0
- data/lib/couchrest/model/typecast.rb +12 -7
- data/lib/couchrest/model/view.rb +190 -0
- data/lib/couchrest/model/views.rb +3 -3
- data/lib/couchrest/model.rb +1 -1
- data/lib/couchrest/railtie.rb +3 -2
- data/lib/couchrest_model.rb +7 -14
- data/lib/rails/generators/couchrest_model/model/model_generator.rb +2 -1
- data/spec/.gitignore +1 -0
- data/spec/couchrest/base_spec.rb +3 -3
- data/spec/couchrest/casted_model_spec.rb +63 -49
- data/spec/couchrest/class_proxy_spec.rb +6 -0
- data/spec/couchrest/configuration_spec.rb +78 -0
- data/spec/couchrest/persistence_spec.rb +10 -4
- data/spec/couchrest/{attribute_protection_spec.rb → property_protection_spec.rb} +29 -2
- data/spec/couchrest/property_spec.rb +61 -0
- data/spec/couchrest/subclass_spec.rb +2 -2
- data/spec/couchrest/view_spec.rb +6 -0
- data/spec/fixtures/more/article.rb +1 -1
- data/spec/spec_helper.rb +4 -3
- metadata +96 -32
- data/lib/couchrest/model/attribute_protection.rb +0 -74
- data/lib/couchrest/model/attributes.rb +0 -75
@@ -31,11 +31,11 @@ class WithCastedCallBackModel < Hash
|
|
31
31
|
property :name
|
32
32
|
property :run_before_validate
|
33
33
|
property :run_after_validate
|
34
|
-
|
34
|
+
|
35
35
|
before_validate do |object|
|
36
36
|
object.run_before_validate = true
|
37
37
|
end
|
38
|
-
after_validate do |object|
|
38
|
+
after_validate do |object|
|
39
39
|
object.run_after_validate = true
|
40
40
|
end
|
41
41
|
end
|
@@ -47,7 +47,7 @@ class CastedCallbackDoc < CouchRest::Model::Base
|
|
47
47
|
end
|
48
48
|
|
49
49
|
describe CouchRest::Model::CastedModel do
|
50
|
-
|
50
|
+
|
51
51
|
describe "A non hash class including CastedModel" do
|
52
52
|
it "should fail raising and include error" do
|
53
53
|
lambda do
|
@@ -55,27 +55,27 @@ describe CouchRest::Model::CastedModel do
|
|
55
55
|
include CouchRest::CastedModel
|
56
56
|
property :name
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
end.should raise_error
|
60
60
|
end
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
describe "isolated" do
|
64
64
|
before(:each) do
|
65
65
|
@obj = WithCastedModelMixin.new
|
66
66
|
end
|
67
67
|
it "should automatically include the property mixin and define getters and setters" do
|
68
68
|
@obj.name = 'Matt'
|
69
|
-
@obj.name.should == 'Matt'
|
69
|
+
@obj.name.should == 'Matt'
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
it "should allow override of default" do
|
73
73
|
@obj = WithCastedModelMixin.new(:name => 'Eric', :details => {'color' => 'orange'})
|
74
74
|
@obj.name.should == 'Eric'
|
75
75
|
@obj.details['color'].should == 'orange'
|
76
76
|
end
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
describe "casted as an attribute, but without a value" do
|
80
80
|
before(:each) do
|
81
81
|
@obj = DummyModel.new
|
@@ -99,22 +99,22 @@ describe CouchRest::Model::CastedModel do
|
|
99
99
|
@obj.sub_models.first.title.should eql('test')
|
100
100
|
end
|
101
101
|
end
|
102
|
-
|
102
|
+
|
103
103
|
describe "casted as attribute" do
|
104
104
|
before(:each) do
|
105
105
|
casted = {:name => 'not whatever'}
|
106
106
|
@obj = DummyModel.new(:casted_attribute => {:name => 'whatever', :casted_attribute => casted})
|
107
107
|
@casted_obj = @obj.casted_attribute
|
108
108
|
end
|
109
|
-
|
109
|
+
|
110
110
|
it "should be available from its parent" do
|
111
111
|
@casted_obj.should be_an_instance_of(WithCastedModelMixin)
|
112
112
|
end
|
113
|
-
|
113
|
+
|
114
114
|
it "should have the getters defined" do
|
115
115
|
@casted_obj.name.should == 'whatever'
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
it "should know who casted it" do
|
119
119
|
@casted_obj.casted_by.should == @obj
|
120
120
|
end
|
@@ -126,27 +126,32 @@ describe CouchRest::Model::CastedModel do
|
|
126
126
|
it "should return nil for the unknown attribute" do
|
127
127
|
@casted_obj["unknown"].should be_nil
|
128
128
|
end
|
129
|
-
|
129
|
+
|
130
130
|
it "should return {} for the hash attribute" do
|
131
131
|
@casted_obj.details.should == {}
|
132
132
|
end
|
133
|
-
|
133
|
+
|
134
134
|
it "should cast its own attributes" do
|
135
135
|
@casted_obj.casted_attribute.should be_instance_of(WithCastedModelMixin)
|
136
136
|
end
|
137
|
+
|
138
|
+
it "should raise an error if save or update_attributes called" do
|
139
|
+
expect { @casted_obj.casted_attribute.save }.to raise_error(NoMethodError)
|
140
|
+
expect { @casted_obj.casted_attribute.update_attributes(:name => "Fubar") }.to raise_error(NoMethodError)
|
141
|
+
end
|
137
142
|
end
|
138
|
-
|
143
|
+
|
139
144
|
describe "casted as an array of a different type" do
|
140
145
|
before(:each) do
|
141
146
|
@obj = DummyModel.new(:keywords => ['couch', 'sofa', 'relax', 'canapé'])
|
142
147
|
end
|
143
|
-
|
148
|
+
|
144
149
|
it "should cast the array properly" do
|
145
150
|
@obj.keywords.should be_an_instance_of(Array)
|
146
151
|
@obj.keywords.first.should == 'couch'
|
147
152
|
end
|
148
153
|
end
|
149
|
-
|
154
|
+
|
150
155
|
describe "update attributes without saving" do
|
151
156
|
before(:each) do
|
152
157
|
@question = Question.new(:q => "What is your quest?", :a => "To seek the Holy Grail")
|
@@ -158,20 +163,20 @@ describe CouchRest::Model::CastedModel do
|
|
158
163
|
@question['q'].should == "What is your favorite color?"
|
159
164
|
@question.a.should == "Blue"
|
160
165
|
end
|
161
|
-
|
166
|
+
|
162
167
|
it "should also work for attributes= alias" do
|
163
168
|
@question.respond_to?(:attributes=).should be_true
|
164
169
|
@question.attributes = {:q => "What is your favorite color?", 'a' => "Blue"}
|
165
170
|
@question['q'].should == "What is your favorite color?"
|
166
171
|
@question.a.should == "Blue"
|
167
172
|
end
|
168
|
-
|
173
|
+
|
169
174
|
it "should flip out if an attribute= method is missing" do
|
170
175
|
lambda {
|
171
176
|
@q.update_attributes_without_saving('foo' => "something", :a => "No green")
|
172
177
|
}.should raise_error(NoMethodError)
|
173
178
|
end
|
174
|
-
|
179
|
+
|
175
180
|
it "should not change any attributes if there is an error" do
|
176
181
|
lambda {
|
177
182
|
@q.update_attributes_without_saving('foo' => "something", :a => "No green")
|
@@ -179,8 +184,9 @@ describe CouchRest::Model::CastedModel do
|
|
179
184
|
@question.q.should == "What is your quest?"
|
180
185
|
@question.a.should == "To seek the Holy Grail"
|
181
186
|
end
|
187
|
+
|
182
188
|
end
|
183
|
-
|
189
|
+
|
184
190
|
describe "saved document with casted models" do
|
185
191
|
before(:each) do
|
186
192
|
reset_test_db!
|
@@ -188,24 +194,24 @@ describe CouchRest::Model::CastedModel do
|
|
188
194
|
@obj.save.should be_true
|
189
195
|
@obj = DummyModel.get(@obj.id)
|
190
196
|
end
|
191
|
-
|
197
|
+
|
192
198
|
it "should be able to load with the casted models" do
|
193
199
|
casted_obj = @obj.casted_attribute
|
194
200
|
casted_obj.should_not be_nil
|
195
201
|
casted_obj.should be_an_instance_of(WithCastedModelMixin)
|
196
202
|
end
|
197
|
-
|
203
|
+
|
198
204
|
it "should have defined getters for the casted model" do
|
199
205
|
casted_obj = @obj.casted_attribute
|
200
206
|
casted_obj.name.should == "whatever"
|
201
207
|
end
|
202
|
-
|
208
|
+
|
203
209
|
it "should have defined setters for the casted model" do
|
204
210
|
casted_obj = @obj.casted_attribute
|
205
211
|
casted_obj.name = "test"
|
206
212
|
casted_obj.name.should == "test"
|
207
213
|
end
|
208
|
-
|
214
|
+
|
209
215
|
it "should retain an override of a casted model attribute's default" do
|
210
216
|
casted_obj = @obj.casted_attribute
|
211
217
|
casted_obj.details['color'] = 'orange'
|
@@ -213,7 +219,7 @@ describe CouchRest::Model::CastedModel do
|
|
213
219
|
casted_obj = DummyModel.get(@obj.id).casted_attribute
|
214
220
|
casted_obj.details['color'].should == 'orange'
|
215
221
|
end
|
216
|
-
|
222
|
+
|
217
223
|
end
|
218
224
|
|
219
225
|
describe "saving document with array of casted models and validation" do
|
@@ -238,7 +244,7 @@ describe CouchRest::Model::CastedModel do
|
|
238
244
|
@cat.should_not be_valid
|
239
245
|
@cat.save.should be_false
|
240
246
|
end
|
241
|
-
|
247
|
+
|
242
248
|
it "should not fail if the casted model doesn't have validation" do
|
243
249
|
Cat.property :masters, [Person], :default => []
|
244
250
|
Cat.validates_presence_of :name
|
@@ -248,7 +254,7 @@ describe CouchRest::Model::CastedModel do
|
|
248
254
|
cat.should be_valid
|
249
255
|
end
|
250
256
|
end
|
251
|
-
|
257
|
+
|
252
258
|
describe "calling valid?" do
|
253
259
|
before :each do
|
254
260
|
@cat = Cat.new
|
@@ -259,7 +265,7 @@ describe CouchRest::Model::CastedModel do
|
|
259
265
|
@cat.toys << @toy2
|
260
266
|
@cat.toys << @toy3
|
261
267
|
end
|
262
|
-
|
268
|
+
|
263
269
|
describe "on the top document" do
|
264
270
|
it "should put errors on all invalid casted models" do
|
265
271
|
@cat.should_not be_valid
|
@@ -268,10 +274,10 @@ describe CouchRest::Model::CastedModel do
|
|
268
274
|
@toy2.errors.should_not be_empty
|
269
275
|
@toy3.errors.should_not be_empty
|
270
276
|
end
|
271
|
-
|
277
|
+
|
272
278
|
it "should not put errors on valid casted models" do
|
273
279
|
@toy1.name = "Feather"
|
274
|
-
@toy2.name = "Twine"
|
280
|
+
@toy2.name = "Twine"
|
275
281
|
@cat.should_not be_valid
|
276
282
|
@cat.errors.should_not be_empty
|
277
283
|
@toy1.errors.should be_empty
|
@@ -279,7 +285,7 @@ describe CouchRest::Model::CastedModel do
|
|
279
285
|
@toy3.errors.should_not be_empty
|
280
286
|
end
|
281
287
|
end
|
282
|
-
|
288
|
+
|
283
289
|
describe "on a casted model property" do
|
284
290
|
it "should only validate itself" do
|
285
291
|
@toy1.should_not be_valid
|
@@ -289,7 +295,7 @@ describe CouchRest::Model::CastedModel do
|
|
289
295
|
@toy3.errors.should be_empty
|
290
296
|
end
|
291
297
|
end
|
292
|
-
|
298
|
+
|
293
299
|
describe "on a casted model inside a casted collection" do
|
294
300
|
it "should only validate itself" do
|
295
301
|
@toy2.should_not be_valid
|
@@ -300,7 +306,7 @@ describe CouchRest::Model::CastedModel do
|
|
300
306
|
end
|
301
307
|
end
|
302
308
|
end
|
303
|
-
|
309
|
+
|
304
310
|
describe "calling new? on a casted model" do
|
305
311
|
before :each do
|
306
312
|
reset_test_db!
|
@@ -309,18 +315,18 @@ describe CouchRest::Model::CastedModel do
|
|
309
315
|
@cat.favorite_toy = @favorite_toy
|
310
316
|
@cat.toys << CatToy.new(:name => 'Fuzzy Stick')
|
311
317
|
end
|
312
|
-
|
318
|
+
|
313
319
|
it "should be true on new" do
|
314
320
|
CatToy.new.should be_new
|
315
321
|
CatToy.new.new_record?.should be_true
|
316
322
|
end
|
317
|
-
|
323
|
+
|
318
324
|
it "should be true after assignment" do
|
319
325
|
@cat.should be_new
|
320
326
|
@cat.favorite_toy.should be_new
|
321
327
|
@cat.toys.first.should be_new
|
322
328
|
end
|
323
|
-
|
329
|
+
|
324
330
|
it "should not be true after create or save" do
|
325
331
|
@cat.create
|
326
332
|
@cat.save
|
@@ -328,14 +334,14 @@ describe CouchRest::Model::CastedModel do
|
|
328
334
|
@cat.toys.first.casted_by.should eql(@cat)
|
329
335
|
@cat.toys.first.should_not be_new
|
330
336
|
end
|
331
|
-
|
337
|
+
|
332
338
|
it "should not be true after get from the database" do
|
333
339
|
@cat.save
|
334
340
|
@cat = Cat.get(@cat.id)
|
335
341
|
@cat.favorite_toy.should_not be_new
|
336
342
|
@cat.toys.first.should_not be_new
|
337
343
|
end
|
338
|
-
|
344
|
+
|
339
345
|
it "should still be true after a failed create or save" do
|
340
346
|
@cat.name = nil
|
341
347
|
@cat.create.should be_false
|
@@ -344,7 +350,7 @@ describe CouchRest::Model::CastedModel do
|
|
344
350
|
@cat.toys.first.should be_new
|
345
351
|
end
|
346
352
|
end
|
347
|
-
|
353
|
+
|
348
354
|
describe "calling base_doc from a nested casted model" do
|
349
355
|
before :each do
|
350
356
|
@course = Course.new(:title => 'Science 101')
|
@@ -357,7 +363,15 @@ describe CouchRest::Model::CastedModel do
|
|
357
363
|
@cat.favorite_toy = @toy1
|
358
364
|
@cat.toys << @toy2
|
359
365
|
end
|
360
|
-
|
366
|
+
|
367
|
+
it 'should let you copy over casted arrays' do
|
368
|
+
question = Question.new
|
369
|
+
@course.questions << question
|
370
|
+
new_course = Course.new
|
371
|
+
new_course.questions = @course.questions
|
372
|
+
new_course.questions.should include(question)
|
373
|
+
end
|
374
|
+
|
361
375
|
it "should reference the top document for" do
|
362
376
|
@course.base_doc.should === @course
|
363
377
|
@professor.casted_by.should === @course
|
@@ -366,19 +380,19 @@ describe CouchRest::Model::CastedModel do
|
|
366
380
|
@toy1.base_doc.should === @course
|
367
381
|
@toy2.base_doc.should === @course
|
368
382
|
end
|
369
|
-
|
383
|
+
|
370
384
|
it "should call setter on top document" do
|
371
385
|
@toy1.base_doc.should_not be_nil
|
372
386
|
@toy1.base_doc.title = 'Tom Foolery'
|
373
387
|
@course.title.should == 'Tom Foolery'
|
374
388
|
end
|
375
|
-
|
389
|
+
|
376
390
|
it "should return nil if not yet casted" do
|
377
391
|
person = Person.new
|
378
392
|
person.base_doc.should == nil
|
379
393
|
end
|
380
394
|
end
|
381
|
-
|
395
|
+
|
382
396
|
describe "calling base_doc.save from a nested casted model" do
|
383
397
|
before :each do
|
384
398
|
reset_test_db!
|
@@ -386,13 +400,13 @@ describe CouchRest::Model::CastedModel do
|
|
386
400
|
@toy = CatToy.new
|
387
401
|
@cat.favorite_toy = @toy
|
388
402
|
end
|
389
|
-
|
403
|
+
|
390
404
|
it "should not save parent document when casted model is invalid" do
|
391
405
|
@toy.should_not be_valid
|
392
406
|
@toy.base_doc.save.should be_false
|
393
407
|
lambda{@toy.base_doc.save!}.should raise_error
|
394
408
|
end
|
395
|
-
|
409
|
+
|
396
410
|
it "should save parent document when nested casted model is valid" do
|
397
411
|
@toy.name = "Mr Squeaks"
|
398
412
|
@toy.should be_valid
|
@@ -400,14 +414,14 @@ describe CouchRest::Model::CastedModel do
|
|
400
414
|
lambda{@toy.base_doc.save!}.should_not raise_error
|
401
415
|
end
|
402
416
|
end
|
403
|
-
|
417
|
+
|
404
418
|
describe "callbacks" do
|
405
419
|
before(:each) do
|
406
420
|
@doc = CastedCallbackDoc.new
|
407
421
|
@model = WithCastedCallBackModel.new
|
408
422
|
@doc.callback_model = @model
|
409
423
|
end
|
410
|
-
|
424
|
+
|
411
425
|
describe "validate" do
|
412
426
|
it "should run before_validate before validating" do
|
413
427
|
@model.run_before_validate.should be_nil
|
@@ -418,7 +432,7 @@ describe CouchRest::Model::CastedModel do
|
|
418
432
|
@model.run_after_validate.should be_nil
|
419
433
|
@model.should be_valid
|
420
434
|
@model.run_after_validate.should be_true
|
421
|
-
end
|
435
|
+
end
|
422
436
|
end
|
423
437
|
end
|
424
438
|
end
|
@@ -87,6 +87,12 @@ describe "Proxy Class" do
|
|
87
87
|
u = @us.first
|
88
88
|
u.title.should =~ /\A...\z/
|
89
89
|
end
|
90
|
+
|
91
|
+
it "should get last" do
|
92
|
+
u = @us.last
|
93
|
+
u.title.should == "aaa"
|
94
|
+
end
|
95
|
+
|
90
96
|
it "should set database on first retreived document" do
|
91
97
|
u = @us.first
|
92
98
|
u.database.should === DB
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
3
|
+
require File.join(FIXTURE_PATH, 'more', 'cat')
|
4
|
+
|
5
|
+
describe CouchRest::Model::Base do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@class = Class.new(CouchRest::Model::Base)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.configure' do
|
12
|
+
it "should set a configuration parameter" do
|
13
|
+
@class.add_config :foo_bar
|
14
|
+
@class.configure do |config|
|
15
|
+
config.foo_bar = 'monkey'
|
16
|
+
end
|
17
|
+
@class.foo_bar.should == 'monkey'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.add_config' do
|
22
|
+
|
23
|
+
it "should add a class level accessor" do
|
24
|
+
@class.add_config :foo_bar
|
25
|
+
@class.foo_bar = 'foo'
|
26
|
+
@class.foo_bar.should == 'foo'
|
27
|
+
end
|
28
|
+
|
29
|
+
['foo', :foo, 45, ['foo', :bar]].each do |val|
|
30
|
+
it "should be inheritable for a #{val.class}" do
|
31
|
+
@class.add_config :foo_bar
|
32
|
+
@child_class = Class.new(@class)
|
33
|
+
|
34
|
+
@class.foo_bar = val
|
35
|
+
@class.foo_bar.should == val
|
36
|
+
@child_class.foo_bar.should == val
|
37
|
+
|
38
|
+
@child_class.foo_bar = "bar"
|
39
|
+
@child_class.foo_bar.should == "bar"
|
40
|
+
|
41
|
+
@class.foo_bar.should == val
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
it "should add an instance level accessor" do
|
47
|
+
@class.add_config :foo_bar
|
48
|
+
@class.foo_bar = 'foo'
|
49
|
+
@class.new.foo_bar.should == 'foo'
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should add a convenient in-class setter" do
|
53
|
+
@class.add_config :foo_bar
|
54
|
+
@class.foo_bar "monkey"
|
55
|
+
@class.foo_bar.should == "monkey"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "General examples" do
|
60
|
+
|
61
|
+
before(:all) do
|
62
|
+
@default_model_key = 'model'
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
it "should be possible to override on class using configure method" do
|
67
|
+
default_model_key = Cat.model_type_key
|
68
|
+
Cat.instance_eval do
|
69
|
+
model_type_key 'cat-type'
|
70
|
+
end
|
71
|
+
CouchRest::Model::Base.model_type_key.should eql(default_model_key)
|
72
|
+
Cat.model_type_key.should eql('cat-type')
|
73
|
+
cat = Cat.new
|
74
|
+
cat.model_type_key.should eql('cat-type')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -25,7 +25,7 @@ describe "Model Persistence" do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should instantialize document of different type" do
|
28
|
-
doc = Article.create_from_database({'_id' => 'testitem2', '_rev' => 123,
|
28
|
+
doc = Article.create_from_database({'_id' => 'testitem2', '_rev' => 123, Article.model_type_key => 'WithTemplateAndUniqueID', 'name' => 'my test'})
|
29
29
|
doc.class.should eql(WithTemplateAndUniqueID)
|
30
30
|
end
|
31
31
|
|
@@ -114,7 +114,7 @@ describe "Model Persistence" do
|
|
114
114
|
end
|
115
115
|
|
116
116
|
it "should set the type" do
|
117
|
-
@sobj[
|
117
|
+
@sobj[@sobj.model_type_key].should == 'Basic'
|
118
118
|
end
|
119
119
|
|
120
120
|
it "should accept true or false on save for validation" do
|
@@ -282,11 +282,17 @@ describe "Model Persistence" do
|
|
282
282
|
foundart = Article.get 'matt aimonetti'
|
283
283
|
foundart.should be_nil
|
284
284
|
end
|
285
|
+
it "should return nil if a blank id is requested" do
|
286
|
+
Article.get("").should be_nil
|
287
|
+
end
|
285
288
|
it "should raise an error if `get!` is used and the document doesn't exist" do
|
286
|
-
|
289
|
+
expect{ Article.get!('matt aimonetti') }.to raise_error
|
290
|
+
end
|
291
|
+
it "should raise an error if `get!` is requested with a blank id" do
|
292
|
+
expect{ Article.get!("") }.to raise_error
|
287
293
|
end
|
288
294
|
it "should raise an error if `find!` is used and the document doesn't exist" do
|
289
|
-
|
295
|
+
expect{ Article.find!('matt aimonetti') }.to raise_error
|
290
296
|
end
|
291
297
|
end
|
292
298
|
|
@@ -34,6 +34,12 @@ describe "Model Attributes" do
|
|
34
34
|
user.name.should == "will"
|
35
35
|
user.phone.should == "555-5555"
|
36
36
|
end
|
37
|
+
|
38
|
+
it "should provide a list of all properties as accessible" do
|
39
|
+
user = NoProtection.new(:name => "will", :phone => "555-5555")
|
40
|
+
user.accessible_properties.length.should eql(2)
|
41
|
+
user.protected_properties.should be_empty
|
42
|
+
end
|
37
43
|
end
|
38
44
|
|
39
45
|
describe "Model Base", "accessible flag" do
|
@@ -65,6 +71,12 @@ describe "Model Attributes" do
|
|
65
71
|
user.name.should == "will"
|
66
72
|
user.admin.should == false
|
67
73
|
end
|
74
|
+
|
75
|
+
it "should provide correct accessible and protected property lists" do
|
76
|
+
user = WithAccessible.new(:name => 'will', :admin => true)
|
77
|
+
user.accessible_properties.map{|p| p.to_s}.should eql(['name'])
|
78
|
+
user.protected_properties.map{|p| p.to_s}.should eql(['admin'])
|
79
|
+
end
|
68
80
|
end
|
69
81
|
|
70
82
|
describe "Model Base", "protected flag" do
|
@@ -96,6 +108,21 @@ describe "Model Attributes" do
|
|
96
108
|
user.name.should == "will"
|
97
109
|
user.admin.should == false
|
98
110
|
end
|
111
|
+
|
112
|
+
it "should not modify the provided attribute hash" do
|
113
|
+
user = WithProtected.new
|
114
|
+
attrs = {:name => "will", :admin => true}
|
115
|
+
user.attributes = attrs
|
116
|
+
attrs[:admin].should be_true
|
117
|
+
attrs[:name].should eql('will')
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should provide correct accessible and protected property lists" do
|
121
|
+
user = WithProtected.new(:name => 'will', :admin => true)
|
122
|
+
user.accessible_properties.map{|p| p.to_s}.should eql(['name'])
|
123
|
+
user.protected_properties.map{|p| p.to_s}.should eql(['admin'])
|
124
|
+
end
|
125
|
+
|
99
126
|
end
|
100
127
|
|
101
128
|
describe "Model Base", "mixing protected and accessible flags" do
|
@@ -107,7 +134,6 @@ describe "Model Attributes" do
|
|
107
134
|
end
|
108
135
|
|
109
136
|
it { expect { WithBothAndUnspecified.new }.to_not raise_error }
|
110
|
-
it { expect { WithBothAndUnspecified.new(nil) }.to_not raise_error }
|
111
137
|
|
112
138
|
it 'should assume that any unspecified property is protected by default' do
|
113
139
|
user = WithBothAndUnspecified.new(:name => 'will', :admin => true, :phone => '555-1234')
|
@@ -116,6 +142,7 @@ describe "Model Attributes" do
|
|
116
142
|
user.admin.should == false
|
117
143
|
user.phone.should == 'unset phone number'
|
118
144
|
end
|
145
|
+
|
119
146
|
end
|
120
147
|
|
121
148
|
describe "from database" do
|
@@ -151,7 +178,7 @@ describe "Model Attributes" do
|
|
151
178
|
it "Base#all should not strip protected attributes" do
|
152
179
|
# all creates a CollectionProxy
|
153
180
|
docs = WithProtected.all(:key => @user.id)
|
154
|
-
docs.
|
181
|
+
docs.length.should == 1
|
155
182
|
reloaded = docs.first
|
156
183
|
verify_attrs reloaded
|
157
184
|
end
|
@@ -22,6 +22,11 @@ describe "Model properties" do
|
|
22
22
|
@card.properties.map{|p| p.name}.should include("first_name")
|
23
23
|
end
|
24
24
|
|
25
|
+
it "should list object properties with values" do
|
26
|
+
@card.properties_with_values.should be_an_instance_of(Hash)
|
27
|
+
@card.properties_with_values["first_name"].should == "matt"
|
28
|
+
end
|
29
|
+
|
25
30
|
it "should let you access a property value (getter)" do
|
26
31
|
@card.first_name.should == "matt"
|
27
32
|
end
|
@@ -88,6 +93,7 @@ describe "Model properties" do
|
|
88
93
|
expect { @card.write_attribute(:this_property_should_not_exist, 823) }.to raise_error(ArgumentError)
|
89
94
|
end
|
90
95
|
|
96
|
+
|
91
97
|
it "should let you use write_attribute on readonly properties" do
|
92
98
|
lambda {
|
93
99
|
@card.read_only_value = "foo"
|
@@ -109,6 +115,34 @@ describe "Model properties" do
|
|
109
115
|
end
|
110
116
|
end
|
111
117
|
|
118
|
+
describe "mass updating attributes without property" do
|
119
|
+
|
120
|
+
describe "when mass_assign_any_attribute false" do
|
121
|
+
|
122
|
+
it "should not allow them to be set" do
|
123
|
+
@card.attributes = {:test => 'fooobar'}
|
124
|
+
@card['test'].should be_nil
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "when mass_assign_any_attribute true" do
|
130
|
+
before(:each) do
|
131
|
+
# dup Card class so that no other tests are effected
|
132
|
+
card_class = Card.dup
|
133
|
+
card_class.class_eval do
|
134
|
+
mass_assign_any_attribute true
|
135
|
+
end
|
136
|
+
@card = card_class.new(:first_name => 'Sam')
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should allow them to be updated' do
|
140
|
+
@card.attributes = {:test => 'fooobar'}
|
141
|
+
@card['test'].should eql('fooobar')
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
112
146
|
|
113
147
|
describe "mass assignment protection" do
|
114
148
|
|
@@ -291,12 +325,28 @@ describe "Model properties" do
|
|
291
325
|
@course['estimate'].should eql(-24.35)
|
292
326
|
end
|
293
327
|
|
328
|
+
it 'return float of a number with commas instead of points for decimals' do
|
329
|
+
@course.estimate = '23,35'
|
330
|
+
@course['estimate'].should eql(23.35)
|
331
|
+
end
|
332
|
+
|
333
|
+
it "should handle numbers with commas and points" do
|
334
|
+
@course.estimate = '1,234.00'
|
335
|
+
@course.estimate.should eql(1234.00)
|
336
|
+
end
|
337
|
+
|
338
|
+
it "should handle a mis-match of commas and points and maintain the last one" do
|
339
|
+
@course.estimate = "1,232.434.123,323"
|
340
|
+
@course.estimate.should eql(1232434123.323)
|
341
|
+
end
|
342
|
+
|
294
343
|
[ Object.new, true, '00.0', '0.', '-.0', 'string' ].each do |value|
|
295
344
|
it "does not typecast non-numeric value #{value.inspect}" do
|
296
345
|
@course.estimate = value
|
297
346
|
@course['estimate'].should equal(value)
|
298
347
|
end
|
299
348
|
end
|
349
|
+
|
300
350
|
end
|
301
351
|
|
302
352
|
describe 'when type primitive is a Integer' do
|
@@ -571,6 +621,16 @@ describe "Model properties" do
|
|
571
621
|
@course['ends_at'].min.should eql(t.min)
|
572
622
|
@course['ends_at'].sec.should eql(t.sec)
|
573
623
|
end
|
624
|
+
it 'parses the string without offset' do
|
625
|
+
t = Time.now
|
626
|
+
@course.ends_at = t.strftime("%Y-%m-%d %H:%M:%S")
|
627
|
+
@course['ends_at'].year.should eql(t.year)
|
628
|
+
@course['ends_at'].month.should eql(t.month)
|
629
|
+
@course['ends_at'].day.should eql(t.day)
|
630
|
+
@course['ends_at'].hour.should eql(t.hour)
|
631
|
+
@course['ends_at'].min.should eql(t.min)
|
632
|
+
@course['ends_at'].sec.should eql(t.sec)
|
633
|
+
end
|
574
634
|
end
|
575
635
|
|
576
636
|
it 'does not typecast non-time values' do
|
@@ -814,3 +874,4 @@ describe "Property Class" do
|
|
814
874
|
end
|
815
875
|
|
816
876
|
end
|
877
|
+
|