couchrest_model 1.1.2 → 1.2.0.beta

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.
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