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
@@ -1,352 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe CouchRest::Model::Views do
4
-
5
- class Unattached < CouchRest::Model::Base
6
- property :title
7
- property :questions
8
- property :professor
9
- view_by :title
10
-
11
- # Force the database to always be nil
12
- def self.database
13
- nil
14
- end
15
- end
16
-
17
- describe "ClassMethods" do
18
- # NOTE! Add more unit tests!
19
-
20
- describe "#view" do
21
-
22
- it "should not alter original query" do
23
- options = { :database => DB }
24
- view = Article.view('by_date', options)
25
- options[:database].should eql(DB)
26
- end
27
-
28
- end
29
-
30
- describe "#has_view?" do
31
- it "should check the design doc" do
32
- Article.design_doc.should_receive(:has_view?).with(:test).and_return(true)
33
- Article.has_view?(:test).should be_true
34
- end
35
- end
36
-
37
- describe "#can_reduce_view?" do
38
- it "should check if view has a reduce method" do
39
- Article.design_doc.should_receive(:can_reduce_view?).with(:test).and_return(true)
40
- Article.can_reduce_view?(:test).should be_true
41
- end
42
- end
43
- end
44
-
45
- describe "a model with simple views and a default param" do
46
- before(:all) do
47
- Article.all.map{|a| a.destroy(true)}
48
- Article.database.bulk_delete
49
- written_at = Time.now - 24 * 3600 * 7
50
- @titles = ["this and that", "also interesting", "more fun", "some junk"]
51
- @titles.each do |title|
52
- a = Article.new(:title => title)
53
- a.date = written_at
54
- a.save
55
- written_at += 24 * 3600
56
- end
57
- end
58
- it "should return the matching raw view result" do
59
- view = Article.by_date :raw => true
60
- view['rows'].length.should == 4
61
- end
62
- it "should not include non-Articles" do
63
- Article.database.save_doc({"date" => 1})
64
- view = Article.by_date :raw => true
65
- view['rows'].length.should == 4
66
- end
67
- it "should return the matching objects (with default argument :descending => true)" do
68
- articles = Article.by_date
69
- articles.collect{|a|a.title}.should == @titles.reverse
70
- end
71
- it "should allow you to override default args" do
72
- articles = Article.by_date :descending => false
73
- articles.collect{|a|a.title}.should == @titles
74
- end
75
- it "should allow you to create a new view on the fly" do
76
- lambda{Article.by_title}.should raise_error
77
- Article.view_by :title
78
- lambda{Article.by_title}.should_not raise_error
79
- end
80
- end
81
-
82
- describe "another model with a simple view" do
83
- before(:all) do
84
- reset_test_db!
85
- %w{aaa bbb ddd eee}.each do |title|
86
- Course.new(:title => title).save
87
- end
88
- end
89
- it "should make the design doc upon first query" do
90
- Course.by_title
91
- doc = Course.design_doc
92
- doc['views']['all']['map'].should include('Course')
93
- end
94
- it "should can query via view" do
95
- # register methods with method-missing, for local dispatch. method
96
- # missing lookup table, no heuristics.
97
- view = Course.view :by_title
98
- designed = Course.by_title
99
- view.should == designed
100
- end
101
- it "should get them" do
102
- rs = Course.by_title
103
- rs.length.should == 4
104
- end
105
- it "should yield" do
106
- courses = []
107
- Course.view(:by_title) do |course|
108
- courses << course
109
- end
110
- courses[0]["doc"]["title"].should =='aaa'
111
- end
112
- it "should yield with by_key method" do
113
- courses = []
114
- Course.by_title do |course|
115
- courses << course
116
- end
117
- courses[0]["doc"]["title"].should =='aaa'
118
- end
119
- end
120
-
121
- describe "find a single item using a view" do
122
- before(:all) do
123
- reset_test_db!
124
- %w{aaa bbb ddd eee}.each do |title|
125
- Course.new(:title => title, :active => (title == 'bbb')).save
126
- end
127
- end
128
-
129
- it "should return single matched record with find helper" do
130
- course = Course.find_by_title('bbb')
131
- course.should_not be_nil
132
- course.title.should eql('bbb') # Ensure really is a Course!
133
- end
134
-
135
- it "should return nil if not found" do
136
- course = Course.find_by_title('fff')
137
- course.should be_nil
138
- end
139
-
140
- it "should peform search on view with two properties" do
141
- course = Course.find_by_title_and_active(['bbb', true])
142
- course.should_not be_nil
143
- course.title.should eql('bbb') # Ensure really is a Course!
144
- end
145
-
146
- it "should return nil if not found" do
147
- course = Course.find_by_title_and_active(['bbb', false])
148
- course.should be_nil
149
- end
150
-
151
- it "should raise exception if view not present" do
152
- lambda { Course.find_by_foobar('123') }.should raise_error(NoMethodError)
153
- end
154
-
155
- it "should perform a search directly with specific key" do
156
- course = Course.first_from_view('by_title', 'bbb')
157
- course.title.should eql('bbb')
158
- end
159
-
160
- it "should perform a search directly with specific key with options" do
161
- course = Course.first_from_view('by_title', 'bbb', :reverse => true)
162
- course.title.should eql('bbb')
163
- end
164
-
165
- it "should perform a search directly with range" do
166
- course = Course.first_from_view('by_title', :startkey => 'bbb', :endkey => 'eee')
167
- course.title.should eql('bbb')
168
- end
169
-
170
- it "should perform a search for first when reduce method present" do
171
- course = Course.first_from_view('by_active')
172
- course.should_not be_nil
173
- end
174
-
175
- end
176
-
177
- describe "a ducktype view" do
178
- before(:all) do
179
- reset_test_db!
180
- @id = DB.save_doc({:dept => true})['id']
181
- end
182
- it "should setup" do
183
- duck = Course.get(@id) # from a different db
184
- duck["dept"].should == true
185
- end
186
- it "should make the design doc" do
187
- @as = Course.by_dept
188
- @doc = Course.design_doc
189
- @doc["views"]["by_dept"]["map"].should_not include("couchrest")
190
- end
191
- it "should not look for class" do
192
- @as = Course.by_dept
193
- @as[0]['_id'].should == @id
194
- end
195
- end
196
-
197
- describe "a model class with database provided manually" do
198
- before(:all) do
199
- reset_test_db!
200
- @db = DB
201
- %w{aaa bbb ddd eee}.each do |title|
202
- u = Unattached.new(:title => title)
203
- u.database = @db
204
- u.save
205
- @first_id ||= u.id
206
- end
207
- end
208
- it "should barf on all if no database given" do
209
- lambda{Unattached.all}.should raise_error
210
- end
211
- it "should query all" do
212
- rs = Unattached.all :database => @db
213
- rs.length.should == 4
214
- end
215
- it "should barf on query if no database given" do
216
- lambda{Unattached.view :by_title}.should raise_error
217
- end
218
- it "should make the design doc upon first query" do
219
- Unattached.by_title :database => @db
220
- doc = Unattached.design_doc
221
- doc['views']['all']['map'].should include('Unattached')
222
- end
223
- it "should merge query params" do
224
- rs = Unattached.by_title :database=>@db, :startkey=>"bbb", :endkey=>"eee"
225
- rs.length.should == 3
226
- end
227
- it "should query via view" do
228
- view = Unattached.view :by_title, :database=>@db
229
- designed = Unattached.by_title :database=>@db
230
- view.should == designed
231
- end
232
- it "should yield" do
233
- things = []
234
- Unattached.view(:by_title, :database=>@db) do |thing|
235
- things << thing
236
- end
237
- things[0]["doc"]["title"].should =='aaa'
238
- end
239
- it "should yield with by_key method" do
240
- things = []
241
- Unattached.by_title(:database=>@db) do |thing|
242
- things << thing
243
- end
244
- things[0]["doc"]["title"].should =='aaa'
245
- end
246
- it "should return nil on get if no database given" do
247
- Unattached.get("aaa").should be_nil
248
- end
249
- it "should barf on get! if no database given" do
250
- lambda{Unattached.get!("aaa")}.should raise_error
251
- end
252
- it "should get from specific database" do
253
- u = Unattached.get(@first_id, @db)
254
- u.title.should == "aaa"
255
- end
256
- it "should barf on first if no database given" do
257
- lambda{Unattached.first}.should raise_error
258
- end
259
- it "should get first" do
260
- u = Unattached.first :database=>@db
261
- u.title.should =~ /\A...\z/
262
- end
263
-
264
- it "should get last" do
265
- u = Unattached.last :database=>@db
266
- u.title.should == "aaa"
267
- end
268
-
269
- end
270
-
271
- describe "a model with a compound key view" do
272
- before(:all) do
273
- Article.by_user_id_and_date.each{|a| a.destroy(true)}
274
- Article.database.bulk_delete
275
- written_at = Time.now - 24 * 3600 * 7
276
- @titles = ["uniq one", "even more interesting", "less fun", "not junk"]
277
- @user_ids = ["quentin", "aaron"]
278
- @titles.each_with_index do |title,i|
279
- u = i % 2
280
- a = Article.new(:title => title, :user_id => @user_ids[u])
281
- a.date = written_at
282
- a.save
283
- written_at += 24 * 3600
284
- end
285
- end
286
- it "should create the design doc" do
287
- Article.by_user_id_and_date rescue nil
288
- doc = Article.design_doc
289
- doc['views']['by_date'].should_not be_nil
290
- end
291
- it "should sort correctly" do
292
- articles = Article.by_user_id_and_date
293
- articles.collect{|a|a['user_id']}.should == ['aaron', 'aaron', 'quentin',
294
- 'quentin']
295
- articles[1].title.should == 'not junk'
296
- end
297
- it "should be queryable with couchrest options" do
298
- articles = Article.by_user_id_and_date :limit => 1, :startkey => 'quentin'
299
- articles.length.should == 1
300
- articles[0].title.should == "even more interesting"
301
- end
302
- end
303
-
304
- describe "with a custom view" do
305
- before(:all) do
306
- @titles = ["very uniq one", "even less interesting", "some fun",
307
- "really junk", "crazy bob"]
308
- @tags = ["cool", "lame"]
309
- @titles.each_with_index do |title,i|
310
- u = i % 2
311
- a = Article.new(:title => title, :tags => [@tags[u]])
312
- a.save
313
- end
314
- end
315
- it "should be available raw" do
316
- view = Article.by_tags :raw => true
317
- view['rows'].length.should == 5
318
- end
319
-
320
- it "should be default to :reduce => false" do
321
- ars = Article.by_tags
322
- ars.first.tags.first.should == 'cool'
323
- end
324
-
325
- it "should be raw when reduce is true" do
326
- view = Article.by_tags :reduce => true, :group => true
327
- view['rows'].find{|r|r['key'] == 'cool'}['value'].should == 3
328
- end
329
- end
330
-
331
- # TODO: moved to Design, delete
332
- describe "adding a view" do
333
- before(:each) do
334
- reset_test_db!
335
- Article.by_date
336
- @original_doc_rev = Article.stored_design_doc['_rev']
337
- @design_docs = Article.database.documents :startkey => "_design/", :endkey => "_design/\u9999"
338
- end
339
- it "should not create a design doc on view definition" do
340
- Article.view_by :created_at
341
- newdocs = Article.database.documents :startkey => "_design/", :endkey => "_design/\u9999"
342
- newdocs["rows"].length.should == @design_docs["rows"].length
343
- end
344
- it "should create a new version of the design document on view access" do
345
- Article.view_by :updated_at
346
- Article.by_updated_at
347
- @original_doc_rev.should_not == Article.stored_design_doc['_rev']
348
- Article.design_doc["views"].keys.should include("by_updated_at")
349
- end
350
- end
351
-
352
- end