couchrest_model 2.1.0.rc1 → 2.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +15 -4
- data/Gemfile.activesupport-4.x +4 -0
- data/Gemfile.activesupport-5.x +4 -0
- data/README.md +2 -0
- data/VERSION +1 -1
- data/couchrest_model.gemspec +3 -2
- data/history.md +14 -1
- data/lib/couchrest/model/associations.rb +3 -8
- data/lib/couchrest/model/base.rb +15 -7
- data/lib/couchrest/model/casted_array.rb +22 -34
- data/lib/couchrest/model/configuration.rb +2 -0
- data/lib/couchrest/model/design.rb +4 -3
- data/lib/couchrest/model/designs/view.rb +37 -32
- data/lib/couchrest/model/dirty.rb +93 -19
- data/lib/couchrest/model/embeddable.rb +2 -14
- data/lib/couchrest/model/extended_attachments.rb +2 -4
- data/lib/couchrest/model/persistence.rb +14 -17
- data/lib/couchrest/model/properties.rb +46 -54
- data/lib/couchrest/model/property.rb +0 -3
- data/lib/couchrest/model/proxyable.rb +20 -4
- data/lib/couchrest/model/validations/uniqueness.rb +4 -1
- data/lib/couchrest_model.rb +2 -2
- data/spec/fixtures/models/article.rb +1 -1
- data/spec/fixtures/models/card.rb +2 -1
- data/spec/fixtures/models/person.rb +1 -0
- data/spec/fixtures/models/project.rb +3 -0
- data/spec/unit/assocations_spec.rb +73 -73
- data/spec/unit/attachment_spec.rb +34 -34
- data/spec/unit/base_spec.rb +102 -102
- data/spec/unit/casted_array_spec.rb +7 -7
- data/spec/unit/casted_spec.rb +7 -7
- data/spec/unit/configuration_spec.rb +11 -11
- data/spec/unit/connection_spec.rb +30 -30
- data/spec/unit/core_extensions/{time_parsing.rb → time_parsing_spec.rb} +21 -21
- data/spec/unit/design_spec.rb +38 -38
- data/spec/unit/designs/design_mapper_spec.rb +26 -26
- data/spec/unit/designs/migrations_spec.rb +13 -13
- data/spec/unit/designs/view_spec.rb +319 -274
- data/spec/unit/designs_spec.rb +39 -39
- data/spec/unit/dirty_spec.rb +188 -103
- data/spec/unit/embeddable_spec.rb +119 -117
- data/spec/unit/inherited_spec.rb +4 -4
- data/spec/unit/persistence_spec.rb +122 -122
- data/spec/unit/properties_spec.rb +466 -16
- data/spec/unit/property_protection_spec.rb +32 -32
- data/spec/unit/property_spec.rb +45 -436
- data/spec/unit/proxyable_spec.rb +140 -82
- data/spec/unit/subclass_spec.rb +14 -14
- data/spec/unit/translations_spec.rb +5 -5
- data/spec/unit/typecast_spec.rb +131 -131
- data/spec/unit/utils/migrate_spec.rb +2 -2
- data/spec/unit/validations_spec.rb +31 -31
- metadata +27 -12
- data/lib/couchrest/model/casted_hash.rb +0 -84
@@ -3,20 +3,470 @@ require "spec_helper"
|
|
3
3
|
|
4
4
|
describe CouchRest::Model::Properties do
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
context "general functionality" do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
reset_test_db!
|
10
|
+
@card = Card.new(:first_name => "matt")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be accessible from the object" do
|
14
|
+
expect(@card.properties).to be_an_instance_of(Array)
|
15
|
+
expect(@card.properties.map{|p| p.name}).to include("first_name")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should list object properties with values" do
|
19
|
+
expect(@card.attributes).to be_an_instance_of(Hash)
|
20
|
+
expect(@card.read_attributes).to be_an_instance_of(Hash)
|
21
|
+
expect(@card.attributes["first_name"]).to eql("matt")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should let you access a property value (getter)" do
|
25
|
+
expect(@card.first_name).to eql("matt")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should let you set a property value (setter)" do
|
29
|
+
@card.last_name = "Aimonetti"
|
30
|
+
expect(@card.last_name).to eq("Aimonetti")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should not let you set a property value if it's read only" do
|
34
|
+
expect{@card.read_only_value = "test"}.to raise_error(NoMethodError)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should let you use an alias for an attribute" do
|
38
|
+
@card.last_name = "Aimonetti"
|
39
|
+
expect(@card.family_name).to eq("Aimonetti")
|
40
|
+
expect(@card.family_name).to eq(@card.last_name)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should let you use an alias for a casted attribute" do
|
44
|
+
@card.cast_alias = Person.new(:name => ["Aimonetti"])
|
45
|
+
expect(@card.cast_alias.name).to eq(["Aimonetti"])
|
46
|
+
expect(@card.calias.name).to eq(["Aimonetti"])
|
47
|
+
card = Card.new(:first_name => "matt", :cast_alias => {:name => ["Aimonetti"]})
|
48
|
+
expect(card.cast_alias.name).to eq(["Aimonetti"])
|
49
|
+
expect(card.calias.name).to eq(["Aimonetti"])
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should raise error if property name coincides with model type key" do
|
53
|
+
expect { Cat.property(Cat.model_type_key) }.to raise_error(/already used/)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should not raise error if property name coincides with model type key on non-model" do
|
57
|
+
expect { Person.property(Article.model_type_key) }.not_to raise_error
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should be auto timestamped" do
|
61
|
+
expect(@card.created_at).to be_nil
|
62
|
+
expect(@card.updated_at).to be_nil
|
63
|
+
expect(@card.save).to be_truthy
|
64
|
+
expect(@card.created_at).not_to be_nil
|
65
|
+
expect(@card.updated_at).not_to be_nil
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#as_couch_json" do
|
69
|
+
|
70
|
+
it "should provide a simple hash from model" do
|
71
|
+
expect(@card.as_couch_json.class).to eql(Hash)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should remove properties from Hash if value is nil" do
|
75
|
+
@card.last_name = nil
|
76
|
+
expect(@card.as_couch_json.keys.include?('last_name')).to be_falsey
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#as_json" do
|
82
|
+
|
83
|
+
it "should provide a simple hash from model" do
|
84
|
+
expect(@card.as_json.class).to eql(Hash)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should pass options to Active Support's as_json" do
|
88
|
+
@card.last_name = "Aimonetti"
|
89
|
+
expect(@card.as_json(:only => 'last_name')).to eql('last_name' => 'Aimonetti')
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#read_attribute' do
|
95
|
+
it "should let you use read_attribute method" do
|
96
|
+
@card.last_name = "Aimonetti"
|
97
|
+
expect(@card.read_attribute(:last_name)).to eql('Aimonetti')
|
98
|
+
expect(@card.read_attribute('last_name')).to eql('Aimonetti')
|
99
|
+
last_name_prop = @card.properties.find{|p| p.name == 'last_name'}
|
100
|
+
expect(@card.read_attribute(last_name_prop)).to eql('Aimonetti')
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should raise an error if the property does not exist' do
|
104
|
+
expect { @card.read_attribute(:this_property_should_not_exist) }.to raise_error(ArgumentError)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#write_attribute' do
|
109
|
+
it "should let you use write_attribute method" do
|
110
|
+
@card.write_attribute(:last_name, 'Aimonetti 1')
|
111
|
+
expect(@card.last_name).to eql('Aimonetti 1')
|
112
|
+
@card.write_attribute('last_name', 'Aimonetti 2')
|
113
|
+
expect(@card.last_name).to eql('Aimonetti 2')
|
114
|
+
last_name_prop = @card.properties.find{|p| p.name == 'last_name'}
|
115
|
+
@card.write_attribute(last_name_prop, 'Aimonetti 3')
|
116
|
+
expect(@card.last_name).to eql('Aimonetti 3')
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should raise an error if the property does not exist' do
|
120
|
+
expect { @card.write_attribute(:this_property_should_not_exist, 823) }.to raise_error(ArgumentError)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should let you use write_attribute on readonly properties" do
|
124
|
+
expect {
|
125
|
+
@card.read_only_value = "foo"
|
126
|
+
}.to raise_error(NoMethodError)
|
127
|
+
@card.write_attribute(:read_only_value, "foo")
|
128
|
+
expect(@card.read_only_value).to eq('foo')
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should cast via write_attribute" do
|
132
|
+
@card.write_attribute(:cast_alias, {:name => ["Sam", "Lown"]})
|
133
|
+
expect(@card.cast_alias.class).to eql(Person)
|
134
|
+
expect(@card.cast_alias.name.last).to eql("Lown")
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should not cast via write_attribute if property not casted" do
|
138
|
+
@card.write_attribute(:first_name, {:name => "Sam"})
|
139
|
+
expect(@card.first_name.class).to eql(Hash)
|
140
|
+
expect(@card.first_name[:name]).to eql("Sam")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# These tests are light as functionality is covered elsewhere
|
145
|
+
describe "#write_attributes" do
|
146
|
+
|
147
|
+
let :obj do
|
148
|
+
Card.new(:first_name => "matt")
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should update attributes" do
|
152
|
+
obj.write_attributes( :last_name => 'foo' )
|
153
|
+
expect(obj.last_name).to eql('foo')
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should not update protected attributes" do
|
157
|
+
obj.write_attributes(:bg_color => '#000000')
|
158
|
+
expect(obj.bg_color).to_not eql('#000000')
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should not update read_only attributes" do
|
162
|
+
obj.write_attributes(:read_only_value => 'bar')
|
163
|
+
expect(obj.read_only_value).to_not eql('bar')
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should have an #attributes= alias" do
|
167
|
+
expect {
|
168
|
+
obj.attributes = { :last_name => 'foo' }
|
169
|
+
}.to_not raise_error
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
# These tests are light as functionality is covered elsewhere
|
175
|
+
describe "#write_all_attributes" do
|
176
|
+
|
177
|
+
let :obj do
|
178
|
+
Card.new(:first_name => "matt")
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should set regular properties" do
|
182
|
+
obj.write_all_attributes(:last_name => 'foo')
|
183
|
+
expect(obj.last_name).to eql('foo')
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should set read-only and protected properties" do
|
187
|
+
obj.write_all_attributes(
|
188
|
+
:read_only_value => 'foo',
|
189
|
+
:bg_color => '#111111'
|
190
|
+
)
|
191
|
+
expect(obj.read_only_value).to eql('foo')
|
192
|
+
expect(obj.bg_color).to eql('#111111')
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
describe "mass updating attributes without property" do
|
199
|
+
|
200
|
+
describe "when mass_assign_any_attribute false" do
|
201
|
+
|
202
|
+
it "should not allow them to be set" do
|
203
|
+
@card.attributes = {:test => 'fooobar'}
|
204
|
+
expect(@card['test']).to be_nil
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should not allow them to be updated with update_attributes' do
|
208
|
+
@card.update_attributes(:test => 'fooobar')
|
209
|
+
expect(@card['test']).to be_nil
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'should not have a different revision after update_attributes' do
|
213
|
+
@card.save
|
214
|
+
rev = @card.rev
|
215
|
+
@card.update_attributes(:test => 'fooobar')
|
216
|
+
expect(@card.rev).to eql(rev)
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'should not have a different revision after save' do
|
220
|
+
@card.save
|
221
|
+
rev = @card.rev
|
222
|
+
@card.attributes = {:test => 'fooobar'}
|
223
|
+
@card.save
|
224
|
+
expect(@card.rev).to eql(rev)
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "when mass_assign_any_attribute true" do
|
230
|
+
before(:each) do
|
231
|
+
# dup Card class so that no other tests are effected
|
232
|
+
card_class = Card.dup
|
233
|
+
card_class.class_eval do
|
234
|
+
mass_assign_any_attribute true
|
235
|
+
end
|
236
|
+
@card = card_class.new(:first_name => 'Sam')
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'should allow them to be updated' do
|
240
|
+
@card.attributes = {:testing => 'fooobar'}
|
241
|
+
expect(@card['testing']).to eql('fooobar')
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'should allow them to be updated with update_attributes' do
|
245
|
+
@card.update_attributes(:testing => 'fooobar')
|
246
|
+
expect(@card['testing']).to eql('fooobar')
|
247
|
+
end
|
248
|
+
|
249
|
+
it 'should have a different revision after update_attributes' do
|
250
|
+
@card.save
|
251
|
+
rev = @card.rev
|
252
|
+
@card.update_attributes(:testing => 'fooobar')
|
253
|
+
expect(@card.rev).not_to eql(rev)
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'should have a different revision after save' do
|
257
|
+
@card.save
|
258
|
+
rev = @card.rev
|
259
|
+
@card.attributes = {:testing => 'fooobar'}
|
260
|
+
@card.save
|
261
|
+
expect(@card.rev).not_to eql(rev)
|
262
|
+
end
|
263
|
+
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
describe "mass assignment protection" do
|
268
|
+
|
269
|
+
it "should not store protected attribute using mass assignment" do
|
270
|
+
cat_toy = CatToy.new(:name => "Zorro")
|
271
|
+
cat = Cat.create(:name => "Helena", :toys => [cat_toy], :favorite_toy => cat_toy, :number => 1)
|
272
|
+
expect(cat.number).to be_nil
|
273
|
+
cat.number = 1
|
274
|
+
cat.save
|
275
|
+
expect(cat.number).to eq(1)
|
276
|
+
end
|
277
|
+
|
278
|
+
it "should not store protected attribute when 'declare accessible poperties, assume all the rest are protected'" do
|
279
|
+
user = User.create(:name => "Marcos Tapajós", :admin => true)
|
280
|
+
expect(user.admin).to be_nil
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should not store protected attribute when 'declare protected properties, assume all the rest are accessible'" do
|
284
|
+
user = SpecialUser.create(:name => "Marcos Tapajós", :admin => true)
|
285
|
+
expect(user.admin).to be_nil
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
289
|
+
|
290
|
+
describe "validation" do
|
291
|
+
before(:each) do
|
292
|
+
@invoice = Invoice.new(:client_name => "matt", :employee_name => "Chris", :location => "San Diego, CA")
|
293
|
+
end
|
294
|
+
|
295
|
+
it "should be able to be validated" do
|
296
|
+
expect(@card.valid?).to eq(true)
|
297
|
+
end
|
298
|
+
|
299
|
+
it "should let you validate the presence of an attribute" do
|
300
|
+
@card.first_name = nil
|
301
|
+
expect(@card).not_to be_valid
|
302
|
+
expect(@card.errors).not_to be_empty
|
303
|
+
expect(@card.errors[:first_name]).to eq(["can't be blank"])
|
304
|
+
end
|
305
|
+
|
306
|
+
it "should let you look up errors for a field by a string name" do
|
307
|
+
@card.first_name = nil
|
308
|
+
expect(@card).not_to be_valid
|
309
|
+
expect(@card.errors['first_name']).to eq(["can't be blank"])
|
310
|
+
end
|
311
|
+
|
312
|
+
it "should validate the presence of 2 attributes" do
|
313
|
+
@invoice.clear
|
314
|
+
expect(@invoice).not_to be_valid
|
315
|
+
expect(@invoice.errors).not_to be_empty
|
316
|
+
expect(@invoice.errors[:client_name]).to eq(["can't be blank"])
|
317
|
+
expect(@invoice.errors[:employee_name]).not_to be_empty
|
318
|
+
end
|
319
|
+
|
320
|
+
it "should let you set an error message" do
|
321
|
+
@invoice.location = nil
|
322
|
+
@invoice.valid?
|
323
|
+
expect(@invoice.errors[:location]).to eq(["Hey stupid!, you forgot the location"])
|
324
|
+
end
|
325
|
+
|
326
|
+
it "should validate before saving" do
|
327
|
+
@invoice.location = nil
|
328
|
+
expect(@invoice).not_to be_valid
|
329
|
+
expect(@invoice.save).to be_falsey
|
330
|
+
expect(@invoice).to be_new
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
8
334
|
end
|
335
|
+
|
336
|
+
context "casting" do
|
337
|
+
|
338
|
+
describe "properties of hash of casted models" do
|
339
|
+
it "should be able to assign a casted hash to a hash property" do
|
340
|
+
chain = KeyChain.new
|
341
|
+
keys = {"House" => "8==$", "Office" => "<>==U"}
|
342
|
+
chain.keys = keys
|
343
|
+
chain.keys = chain.keys
|
344
|
+
expect(chain.keys).to eq(keys)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
describe "properties of array of casted models" do
|
349
|
+
|
350
|
+
before(:each) do
|
351
|
+
@course = Course.new :title => 'Test Course'
|
352
|
+
end
|
353
|
+
|
354
|
+
it "should allow attribute to be set from an array of objects" do
|
355
|
+
@course.questions = [Question.new(:q => "works?"), Question.new(:q => "Meaning of Life?")]
|
356
|
+
expect(@course.questions.length).to eql(2)
|
357
|
+
end
|
358
|
+
|
359
|
+
it "should allow attribute to be set from an array of hashes" do
|
360
|
+
@course.questions = [{:q => "works?"}, {:q => "Meaning of Life?"}]
|
361
|
+
expect(@course.questions.length).to eql(2)
|
362
|
+
expect(@course.questions.last.q).to eql("Meaning of Life?")
|
363
|
+
expect(@course.questions.last.class).to eql(Question) # typecasting
|
364
|
+
end
|
365
|
+
|
366
|
+
it "should allow attribute to be set from hash with ordered keys and objects" do
|
367
|
+
@course.questions = { '0' => Question.new(:q => "Test1"), '1' => Question.new(:q => 'Test2') }
|
368
|
+
expect(@course.questions.length).to eql(2)
|
369
|
+
expect(@course.questions.last.q).to eql('Test2')
|
370
|
+
expect(@course.questions.last.class).to eql(Question)
|
371
|
+
end
|
372
|
+
|
373
|
+
it "should allow attribute to be set from hash with ordered keys and sub-hashes" do
|
374
|
+
@course.questions = { '10' => {:q => 'Test10'}, '0' => {:q => "Test1"}, '1' => {:q => 'Test2'} }
|
375
|
+
expect(@course.questions.length).to eql(3)
|
376
|
+
expect(@course.questions.last.q).to eql('Test10')
|
377
|
+
expect(@course.questions.last.class).to eql(Question)
|
378
|
+
end
|
379
|
+
|
380
|
+
it "should allow attribute to be set from hash with ordered keys and HashWithIndifferentAccess" do
|
381
|
+
# This is similar to what you'd find in an HTML POST parameters
|
382
|
+
hash = HashWithIndifferentAccess.new({ '0' => {:q => "Test1"}, '1' => {:q => 'Test2'} })
|
383
|
+
@course.questions = hash
|
384
|
+
expect(@course.questions.length).to eql(2)
|
385
|
+
expect(@course.questions.last.q).to eql('Test2')
|
386
|
+
expect(@course.questions.last.class).to eql(Question)
|
387
|
+
end
|
388
|
+
|
389
|
+
it "should allow attribute to be set from Hash subclass with ordered keys" do
|
390
|
+
ourhash = Class.new(HashWithIndifferentAccess)
|
391
|
+
hash = ourhash.new({ '0' => {:q => "Test1"}, '1' => {:q => 'Test2'} })
|
392
|
+
@course.questions = hash
|
393
|
+
expect(@course.questions.length).to eql(2)
|
394
|
+
expect(@course.questions.last.q).to eql('Test2')
|
395
|
+
expect(@course.questions.last.class).to eql(Question)
|
396
|
+
end
|
397
|
+
|
398
|
+
it "should raise an error if attempting to set single value for array type" do
|
399
|
+
expect {
|
400
|
+
@course.questions = Question.new(:q => 'test1')
|
401
|
+
}.to raise_error(/Expecting an array/)
|
402
|
+
end
|
403
|
+
|
404
|
+
|
405
|
+
end
|
406
|
+
|
407
|
+
describe "a casted model retrieved from the database" do
|
408
|
+
before(:each) do
|
409
|
+
reset_test_db!
|
410
|
+
@cat = Cat.new(:name => 'Stimpy')
|
411
|
+
@cat.favorite_toy = CatToy.new(:name => 'Stinky')
|
412
|
+
@cat.toys << CatToy.new(:name => 'Feather')
|
413
|
+
@cat.toys << CatToy.new(:name => 'Mouse')
|
414
|
+
@cat.save
|
415
|
+
@cat = Cat.get(@cat.id)
|
416
|
+
end
|
417
|
+
|
418
|
+
describe "as a casted property" do
|
419
|
+
it "should already be casted_by its parent" do
|
420
|
+
expect(@cat.favorite_toy.casted_by).to be === @cat
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
describe "from a casted collection" do
|
425
|
+
it "should already be casted_by its parent" do
|
426
|
+
expect(@cat.toys[0].casted_by).to be === @cat
|
427
|
+
expect(@cat.toys[1].casted_by).to be === @cat
|
428
|
+
end
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
describe "nested models (not casted)" do
|
433
|
+
before(:each) do
|
434
|
+
reset_test_db!
|
435
|
+
@cat = ChildCat.new(:name => 'Stimpy')
|
436
|
+
@cat.mother = {:name => 'Stinky'}
|
437
|
+
@cat.siblings = [{:name => 'Feather'}, {:name => 'Felix'}]
|
438
|
+
@cat.save
|
439
|
+
@cat = ChildCat.get(@cat.id)
|
440
|
+
end
|
441
|
+
|
442
|
+
it "should correctly save single relation" do
|
443
|
+
expect(@cat.mother.name).to eql('Stinky')
|
444
|
+
expect(@cat.mother.casted_by).to eql(@cat)
|
445
|
+
end
|
446
|
+
|
447
|
+
it "should correctly save collection" do
|
448
|
+
expect(@cat.siblings.first.name).to eql("Feather")
|
449
|
+
expect(@cat.siblings.last.casted_by).to eql(@cat)
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
end
|
454
|
+
|
455
|
+
context "multipart attributes" do
|
456
|
+
|
457
|
+
before(:each) do
|
458
|
+
@obj = WithDefaultValues.new
|
459
|
+
end
|
9
460
|
|
10
|
-
describe "multipart attributes" do
|
11
461
|
context "with valid params" do
|
12
462
|
it "should parse a legal date" do
|
13
463
|
valid_date_params = { "exec_date(1i)"=>"2011",
|
14
464
|
"exec_date(2i)"=>"10",
|
15
465
|
"exec_date(3i)"=>"18"}
|
16
466
|
@obj = WithDateAndTime.new valid_date_params
|
17
|
-
@obj.exec_date.
|
18
|
-
@obj.exec_date.
|
19
|
-
@obj.exec_date.
|
467
|
+
expect(@obj.exec_date).not_to be_nil
|
468
|
+
expect(@obj.exec_date).to be_kind_of(Date)
|
469
|
+
expect(@obj.exec_date).to eq(Date.new(2011, 10 ,18))
|
20
470
|
end
|
21
471
|
|
22
472
|
it "should parse a legal time" do
|
@@ -27,9 +477,9 @@ describe CouchRest::Model::Properties do
|
|
27
477
|
"exec_time(5i)"=>"15",
|
28
478
|
"exec_time(6i)"=>"15",}
|
29
479
|
@obj = WithDateAndTime.new valid_time_params
|
30
|
-
@obj.exec_time.
|
31
|
-
@obj.exec_time.
|
32
|
-
@obj.exec_time.
|
480
|
+
expect(@obj.exec_time).not_to be_nil
|
481
|
+
expect(@obj.exec_time).to be_kind_of(Time)
|
482
|
+
expect(@obj.exec_time).to eq(Time.utc(2011, 10 ,18, 15, 15, 15))
|
33
483
|
end
|
34
484
|
end
|
35
485
|
|
@@ -41,15 +491,15 @@ describe CouchRest::Model::Properties do
|
|
41
491
|
end
|
42
492
|
it "should still create a model if there are invalid attributes" do
|
43
493
|
@obj = WithDateAndTime.new @invalid_date_params
|
44
|
-
@obj.
|
45
|
-
@obj.
|
494
|
+
expect(@obj).not_to be_nil
|
495
|
+
expect(@obj).to be_kind_of(WithDateAndTime)
|
46
496
|
end
|
47
497
|
it "should not crash because of an empty value" do
|
48
498
|
@invalid_date_params["exec_date(2i)"] = ""
|
49
499
|
@obj = WithDateAndTime.new @invalid_date_params
|
50
|
-
@obj.
|
51
|
-
@obj.exec_date.
|
52
|
-
@obj.
|
500
|
+
expect(@obj).not_to be_nil
|
501
|
+
expect(@obj.exec_date).not_to be_kind_of(Date)
|
502
|
+
expect(@obj).to be_kind_of(WithDateAndTime)
|
53
503
|
end
|
54
504
|
end
|
55
505
|
|
@@ -64,9 +514,9 @@ describe CouchRest::Model::Properties do
|
|
64
514
|
end
|
65
515
|
|
66
516
|
it "should be accepted" do
|
67
|
-
|
517
|
+
expect {
|
68
518
|
@obj = klass.new(:name => 'test (object)')
|
69
|
-
}.
|
519
|
+
}.not_to raise_error
|
70
520
|
end
|
71
521
|
|
72
522
|
end
|