couchrest_model 1.1.2 → 1.2.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/README.md +8 -2
  2. data/VERSION +1 -1
  3. data/couchrest_model.gemspec +2 -1
  4. data/history.md +8 -0
  5. data/lib/couchrest/model/base.rb +0 -20
  6. data/lib/couchrest/model/configuration.rb +2 -0
  7. data/lib/couchrest/model/core_extensions/time_parsing.rb +35 -9
  8. data/lib/couchrest/model/designs/design.rb +182 -0
  9. data/lib/couchrest/model/designs/view.rb +91 -48
  10. data/lib/couchrest/model/designs.rb +72 -19
  11. data/lib/couchrest/model/document_queries.rb +15 -45
  12. data/lib/couchrest/model/properties.rb +43 -2
  13. data/lib/couchrest/model/proxyable.rb +20 -54
  14. data/lib/couchrest/model/typecast.rb +1 -1
  15. data/lib/couchrest/model/validations/uniqueness.rb +7 -6
  16. data/lib/couchrest_model.rb +1 -5
  17. data/spec/fixtures/models/article.rb +22 -20
  18. data/spec/fixtures/models/base.rb +15 -7
  19. data/spec/fixtures/models/course.rb +7 -4
  20. data/spec/fixtures/models/project.rb +4 -1
  21. data/spec/fixtures/models/sale_entry.rb +5 -3
  22. data/spec/unit/base_spec.rb +51 -5
  23. data/spec/unit/core_extensions/time_parsing.rb +41 -0
  24. data/spec/unit/designs/design_spec.rb +291 -0
  25. data/spec/unit/designs/view_spec.rb +135 -40
  26. data/spec/unit/designs_spec.rb +341 -30
  27. data/spec/unit/dirty_spec.rb +67 -0
  28. data/spec/unit/inherited_spec.rb +2 -2
  29. data/spec/unit/property_protection_spec.rb +3 -1
  30. data/spec/unit/property_spec.rb +43 -3
  31. data/spec/unit/proxyable_spec.rb +57 -98
  32. data/spec/unit/subclass_spec.rb +14 -5
  33. data/spec/unit/validations_spec.rb +14 -12
  34. metadata +172 -129
  35. data/lib/couchrest/model/class_proxy.rb +0 -135
  36. data/lib/couchrest/model/collection.rb +0 -273
  37. data/lib/couchrest/model/design_doc.rb +0 -115
  38. data/lib/couchrest/model/support/couchrest_design.rb +0 -33
  39. data/lib/couchrest/model/views.rb +0 -148
  40. data/spec/unit/class_proxy_spec.rb +0 -167
  41. data/spec/unit/collection_spec.rb +0 -86
  42. data/spec/unit/design_doc_spec.rb +0 -212
  43. data/spec/unit/view_spec.rb +0 -352
@@ -148,141 +148,101 @@ describe CouchRest::Model::Proxyable do
148
148
  @klass = CouchRest::Model::Proxyable::ModelProxy
149
149
  end
150
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')
151
+ before :each do
152
+ @design_doc = mock('Design')
153
+ @design_doc.stub!(:view_names).and_return(['all', 'by_name'])
154
+ @model = mock('Cat')
155
+ @model.stub!(:design_docs).and_return([@design_doc])
156
+ @obj = @klass.new(@model, 'owner', 'owner_name', 'database')
157
157
  end
158
158
 
159
- describe "instance" do
159
+ describe "initialization" do
160
160
 
161
- before :each do
162
- @obj = @klass.new(Cat, 'owner', 'owner_name', 'database')
161
+ it "should set base attributes" do
162
+ @obj.model.should eql(@model)
163
+ @obj.owner.should eql('owner')
164
+ @obj.owner_name.should eql('owner_name')
165
+ @obj.database.should eql('database')
163
166
  end
164
167
 
165
- it "should proxy new call" do
166
- @obj.should_receive(:proxy_block_update).with(:new, 'attrs', 'opts')
167
- @obj.new('attrs', 'opts')
168
+ it "should create view methods" do
169
+ @obj.should respond_to('all')
170
+ @obj.should respond_to('by_name')
171
+ @obj.should respond_to('find_all')
172
+ @obj.should respond_to('find_by_name')
168
173
  end
169
174
 
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')
175
+ it "should create 'all' view method that forward to model's view with proxy" do
176
+ @model.should_receive(:all).with(:proxy => @obj).and_return(nil)
177
+ @obj.all
173
178
  end
174
179
 
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
180
+ it "should create 'by_name' view method that forward to model's view with proxy" do
181
+ @model.should_receive(:by_name).with(:proxy => @obj).and_return(nil)
182
+ @obj.by_name
183
+ end
185
184
 
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
185
+ it "should create 'find_by_name' view that forwards to normal view" do
186
+ view = mock('view')
187
+ view.should_receive('key').with('name').and_return(view)
188
+ view.should_receive('first').and_return(nil)
189
+ @obj.should_receive(:by_name).and_return(view)
190
+ @obj.find_by_name('name')
191
+ end
193
192
 
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
193
+ end
202
194
 
195
+ describe "instance" do
196
+
197
+ it "should proxy new call" do
198
+ @obj.should_receive(:proxy_block_update).with(:new, 'attrs', 'opts')
199
+ @obj.new('attrs', 'opts')
203
200
  end
204
201
 
205
- it "should proxy #all" do
206
- Cat.should_receive(:all).with({:database => 'database'})
207
- @obj.should_receive(:proxy_update_all)
208
- @obj.all
202
+ it "should proxy build_from_database" do
203
+ @obj.should_receive(:proxy_block_update).with(:build_from_database, 'attrs', 'opts')
204
+ @obj.build_from_database('attrs', 'opts')
209
205
  end
210
-
206
+
211
207
  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)
208
+ view = mock('View')
209
+ view.should_receive(:count).and_return(nil)
210
+ @model.should_receive(:all).and_return(view)
211
+ @obj.count
214
212
  end
215
213
 
216
214
  it "should proxy #first" do
217
- Cat.should_receive(:first).with({:database => 'database'})
218
- @obj.should_receive(:proxy_update)
215
+ view = mock('View')
216
+ view.should_receive(:first).and_return(nil)
217
+ @model.should_receive(:all).and_return(view)
219
218
  @obj.first
220
219
  end
221
220
 
222
221
  it "should proxy #last" do
223
- Cat.should_receive(:last).with({:database => 'database'})
224
- @obj.should_receive(:proxy_update)
222
+ view = mock('View')
223
+ view.should_receive(:last).and_return(nil)
224
+ @model.should_receive(:all).and_return(view)
225
225
  @obj.last
226
226
  end
227
227
 
228
228
  it "should proxy #get" do
229
- Cat.should_receive(:get).with(32, 'database')
229
+ @model.should_receive(:get).with(32, 'database')
230
230
  @obj.should_receive(:proxy_update)
231
231
  @obj.get(32)
232
232
  end
233
233
  it "should proxy #find" do
234
- Cat.should_receive(:get).with(32, 'database')
234
+ @model.should_receive(:get).with(32, 'database')
235
235
  @obj.should_receive(:proxy_update)
236
236
  @obj.find(32)
237
237
  end
238
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
239
 
280
240
  ### Updating methods
281
241
 
282
242
  describe "#proxy_update" do
283
243
  it "should set returned doc fields" do
284
244
  doc = mock(:Document)
285
- doc.should_receive(:is_a?).with(Cat).and_return(true)
245
+ doc.should_receive(:is_a?).with(@model).and_return(true)
286
246
  doc.should_receive(:database=).with('database')
287
247
  doc.should_receive(:model_proxy=).with(@obj)
288
248
  doc.should_receive(:send).with('owner_name=', 'owner')
@@ -291,7 +251,7 @@ describe CouchRest::Model::Proxyable do
291
251
 
292
252
  it "should not set anything if matching document not provided" do
293
253
  doc = mock(:DocumentFoo)
294
- doc.should_receive(:is_a?).with(Cat).and_return(false)
254
+ doc.should_receive(:is_a?).with(@model).and_return(false)
295
255
  doc.should_not_receive(:database=)
296
256
  doc.should_not_receive(:model_proxy=)
297
257
  doc.should_not_receive(:owner_name=)
@@ -343,13 +303,12 @@ describe CouchRest::Model::Proxyable do
343
303
  view :by_total
344
304
  end
345
305
  end
346
-
347
-
348
306
  @company = ProxyableCompany.create(:slug => 'samco')
349
307
  end
350
308
 
351
309
  it "should create the new database" do
352
- @company.proxyable_invoices.all.should be_empty
310
+ view = @company.proxyable_invoices.all
311
+ view.should be_empty
353
312
  TEST_SERVER.databases.find{|db| db =~ /#{TESTDB}-samco/}.should_not be_nil
354
313
  end
355
314
 
@@ -17,13 +17,17 @@ end
17
17
 
18
18
  class OnlineCourse < Course
19
19
  property :url
20
- view_by :url
20
+ design do
21
+ view :by_url
22
+ end
21
23
  end
22
24
 
23
25
  class Animal < CouchRest::Model::Base
24
26
  use_database TEST_SERVER.default_database
25
27
  property :name
26
- view_by :name
28
+ design do
29
+ view :by_name
30
+ end
27
31
  end
28
32
 
29
33
  class Dog < Animal; end
@@ -67,19 +71,24 @@ describe "Subclassing a Model" do
67
71
  end
68
72
 
69
73
  it "should have a design doc slug based on the subclass name" do
70
- OnlineCourse.design_doc_slug.should =~ /^OnlineCourse/
74
+ OnlineCourse.design_doc['_id'].should =~ /OnlineCourse$/
71
75
  end
72
76
 
73
77
  it "should not add views to the parent's design_doc" do
74
78
  Course.design_doc['views'].keys.should_not include('by_url')
75
79
  end
76
80
 
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')
81
+ it "should add the parent's views to its design doc" do
82
+ OnlineCourse.design_doc['views'].keys.should include('by_title')
83
+ end
84
+
85
+ it "should add the parent's views but alter the model names in map function" do
86
+ OnlineCourse.design_doc['views']['by_title']['map'].should =~ /doc\['#{OnlineCourse.model_type_key}'\] == 'OnlineCourse'/
79
87
  end
80
88
 
81
89
  it "should have an all view with a guard clause for model == subclass name in the map function" do
82
90
  OnlineCourse.design_doc['views']['all']['map'].should =~ /if \(doc\['#{OnlineCourse.model_type_key}'\] == 'OnlineCourse'\)/
83
91
  end
92
+
84
93
  end
85
94
 
@@ -10,7 +10,7 @@ describe CouchRest::Model::Validations do
10
10
  end
11
11
 
12
12
  it "should create a new view if none defined before performing" do
13
- WithUniqueValidation.has_view?(:by_title).should be_true
13
+ WithUniqueValidation.design_doc.has_view?(:by_title).should be_true
14
14
  end
15
15
 
16
16
  it "should validate a new unique document" do
@@ -49,16 +49,14 @@ describe CouchRest::Model::Validations do
49
49
 
50
50
  it "should not try to create a defined view" do
51
51
  WithUniqueValidationView.validates_uniqueness_of :title, :view => 'fooobar'
52
- WithUniqueValidationView.has_view?('fooobar').should be_false
53
- WithUniqueValidationView.has_view?('by_title').should be_false
52
+ WithUniqueValidationView.design_doc.has_view?('fooobar').should be_false
53
+ WithUniqueValidationView.design_doc.has_view?('by_title').should be_false
54
54
  end
55
55
 
56
56
 
57
57
  it "should not try to create new view when already defined" do
58
58
  @obj = @objs[1]
59
- @obj.class.should_not_receive('view_by')
60
- @obj.class.should_receive('has_view?').and_return(true)
61
- @obj.class.should_receive('view').and_return({'rows' => [ ]})
59
+ @obj.class.design_doc.should_not_receive('create_view')
62
60
  @obj.valid?
63
61
  end
64
62
  end
@@ -66,7 +64,7 @@ describe CouchRest::Model::Validations do
66
64
  context "with a proxy parameter" do
67
65
 
68
66
  it "should create a new view despite proxy" do
69
- WithUniqueValidationProxy.has_view?(:by_title).should be_true
67
+ WithUniqueValidationProxy.design_doc.has_view?(:by_title).should be_true
70
68
  end
71
69
 
72
70
  it "should be used" do
@@ -77,19 +75,23 @@ describe CouchRest::Model::Validations do
77
75
 
78
76
  it "should allow specific view" do
79
77
  @obj = WithUniqueValidationProxy.new(:title => 'test 7')
80
- @obj.class.should_not_receive('view_by')
78
+ @obj.class.should_not_receive('by_title')
79
+ view = mock('View')
80
+ view.stub!(:rows).and_return([])
81
81
  proxy = mock('Proxy')
82
+ proxy.should_receive('by_title').and_return(view)
83
+ proxy.should_receive('respond_to?').with('by_title').and_return(true)
82
84
  @obj.should_receive('proxy').and_return(proxy)
83
- proxy.should_receive('has_view?').and_return(true)
84
- proxy.should_receive('view').and_return({'rows' => [ ]})
85
85
  @obj.valid?
86
86
  end
87
87
  end
88
88
 
89
89
  context "when proxied" do
90
90
  it "should lookup the model_proxy" do
91
+ view = mock('View')
92
+ view.stub!(:rows).and_return([])
91
93
  mp = mock(:ModelProxy)
92
- mp.should_receive(:view).and_return({'rows' => []})
94
+ mp.should_receive(:by_title).and_return(view)
93
95
  @obj = WithUniqueValidation.new(:title => 'test 8')
94
96
  @obj.stub!(:model_proxy).twice.and_return(mp)
95
97
  @obj.valid?
@@ -103,7 +105,7 @@ describe CouchRest::Model::Validations do
103
105
  end
104
106
 
105
107
  it "should create the view" do
106
- @objs.first.class.has_view?('by_parent_id_and_title')
108
+ @objs.first.class.design_doc.has_view?('by_parent_id_and_title')
107
109
  end
108
110
 
109
111
  it "should validate unique document" do