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.
- data/README.md +8 -2
- data/VERSION +1 -1
- data/couchrest_model.gemspec +2 -1
- data/history.md +8 -0
- data/lib/couchrest/model/base.rb +0 -20
- data/lib/couchrest/model/configuration.rb +2 -0
- data/lib/couchrest/model/core_extensions/time_parsing.rb +35 -9
- data/lib/couchrest/model/designs/design.rb +182 -0
- data/lib/couchrest/model/designs/view.rb +91 -48
- data/lib/couchrest/model/designs.rb +72 -19
- data/lib/couchrest/model/document_queries.rb +15 -45
- data/lib/couchrest/model/properties.rb +43 -2
- data/lib/couchrest/model/proxyable.rb +20 -54
- data/lib/couchrest/model/typecast.rb +1 -1
- data/lib/couchrest/model/validations/uniqueness.rb +7 -6
- data/lib/couchrest_model.rb +1 -5
- data/spec/fixtures/models/article.rb +22 -20
- data/spec/fixtures/models/base.rb +15 -7
- data/spec/fixtures/models/course.rb +7 -4
- data/spec/fixtures/models/project.rb +4 -1
- data/spec/fixtures/models/sale_entry.rb +5 -3
- data/spec/unit/base_spec.rb +51 -5
- data/spec/unit/core_extensions/time_parsing.rb +41 -0
- data/spec/unit/designs/design_spec.rb +291 -0
- data/spec/unit/designs/view_spec.rb +135 -40
- data/spec/unit/designs_spec.rb +341 -30
- data/spec/unit/dirty_spec.rb +67 -0
- data/spec/unit/inherited_spec.rb +2 -2
- data/spec/unit/property_protection_spec.rb +3 -1
- data/spec/unit/property_spec.rb +43 -3
- data/spec/unit/proxyable_spec.rb +57 -98
- data/spec/unit/subclass_spec.rb +14 -5
- data/spec/unit/validations_spec.rb +14 -12
- metadata +172 -129
- data/lib/couchrest/model/class_proxy.rb +0 -135
- data/lib/couchrest/model/collection.rb +0 -273
- data/lib/couchrest/model/design_doc.rb +0 -115
- data/lib/couchrest/model/support/couchrest_design.rb +0 -33
- data/lib/couchrest/model/views.rb +0 -148
- data/spec/unit/class_proxy_spec.rb +0 -167
- data/spec/unit/collection_spec.rb +0 -86
- data/spec/unit/design_doc_spec.rb +0 -212
- data/spec/unit/view_spec.rb +0 -352
data/spec/unit/view_spec.rb
DELETED
@@ -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
|