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,167 +0,0 @@
1
- require "spec_helper"
2
-
3
- class UnattachedDoc < CouchRest::Model::Base
4
- # Note: no use_database here
5
- property :title
6
- property :questions
7
- property :professor
8
- view_by :title
9
- end
10
-
11
-
12
- describe "Proxy Class" do
13
-
14
- before(:all) do
15
- reset_test_db!
16
- # setup the class default doc to save the design doc
17
- UnattachedDoc.use_database nil # just to be sure it is really unattached
18
- @us = UnattachedDoc.on(DB)
19
- %w{aaa bbb ddd eee}.each do |title|
20
- u = @us.new(:title => title)
21
- u.save
22
- @first_id ||= u.id
23
- end
24
- end
25
-
26
- it "should query all" do
27
- rs = @us.all
28
- rs.length.should == 4
29
- end
30
- it "should count" do
31
- @us.count.should == 4
32
- end
33
- it "should make the design doc upon first query" do
34
- @us.by_title
35
- doc = @us.design_doc
36
- doc['views']['all']['map'].should include('UnattachedDoc')
37
- end
38
- it "should merge query params" do
39
- rs = @us.by_title :startkey=>"bbb", :endkey=>"eee"
40
- rs.length.should == 3
41
- end
42
- it "should query via view" do
43
- view = @us.view :by_title
44
- designed = @us.by_title
45
- view.should == designed
46
- end
47
-
48
- it "should query via first_from_view" do
49
- UnattachedDoc.should_receive(:first_from_view).with('by_title', 'bbb', {:database => DB})
50
- @us.first_from_view('by_title', 'bbb')
51
- end
52
-
53
- it "should query via first_from_view with complex options" do
54
- UnattachedDoc.should_receive(:first_from_view).with('by_title', {:key => 'bbb', :database => DB})
55
- @us.first_from_view('by_title', :key => 'bbb')
56
- end
57
-
58
- it "should query via first_from_view with complex extra options" do
59
- UnattachedDoc.should_receive(:first_from_view).with('by_title', 'bbb', {:limit => 1, :database => DB})
60
- @us.first_from_view('by_title', 'bbb', :limit => 1)
61
- end
62
-
63
- it "should allow dynamic view matching for single elements" do
64
- @us.should_receive(:first_from_view).with('by_title', 'bbb')
65
- @us.find_by_title('bbb')
66
- end
67
-
68
- it "should yield" do
69
- things = []
70
- @us.view(:by_title) do |thing|
71
- things << thing
72
- end
73
- things[0]["doc"]["title"].should =='aaa'
74
- end
75
- it "should yield with by_key method" do
76
- things = []
77
- @us.by_title do |thing|
78
- things << thing
79
- end
80
- things[0]["doc"]["title"].should =='aaa'
81
- end
82
- it "should get from specific database" do
83
- u = @us.get(@first_id)
84
- u.title.should == "aaa"
85
- end
86
- it "should get first" do
87
- u = @us.first
88
- u.should == @us.all.first
89
- end
90
-
91
- it "should get last" do
92
- u = @us.last
93
- u.should == @us.all.last
94
- end
95
-
96
- it "should set database on first retreived document" do
97
- u = @us.first
98
- u.database.should === DB
99
- end
100
- it "should set database on all retreived documents" do
101
- @us.all.each do |u|
102
- u.database.should === DB
103
- end
104
- end
105
- it "should set database on each retreived document" do
106
- rs = @us.by_title :startkey=>"bbb", :endkey=>"eee"
107
- rs.length.should == 3
108
- rs.each do |u|
109
- u.database.should === DB
110
- end
111
- end
112
- it "should set database on document retreived by id" do
113
- u = @us.get(@first_id)
114
- u.database.should === DB
115
- end
116
- it "should not attempt to set database on raw results using :all" do
117
- @us.all(:raw => true).each do |u|
118
- u.respond_to?(:database).should be_false
119
- end
120
- end
121
- it "should not attempt to set database on raw results using view" do
122
- @us.by_title(:raw => true).each do |u|
123
- u.respond_to?(:database).should be_false
124
- end
125
- end
126
-
127
- describe "#get!" do
128
- it "raises exception when passed a nil" do
129
- expect { @us.get!(nil)}.to raise_error(CouchRest::Model::DocumentNotFound)
130
- end
131
-
132
- it "raises exception when passed an empty string " do
133
- expect { @us.get!("")}.to raise_error(CouchRest::Model::DocumentNotFound)
134
- end
135
-
136
- it "raises exception when document with provided id does not exist" do
137
- expect { @us.get!("thisisnotreallyadocumentid")}.to raise_error(CouchRest::Model::DocumentNotFound)
138
- end
139
- end
140
-
141
- describe "#find!" do
142
- it "raises exception when passed a nil" do
143
- expect { @us.find!(nil)}.to raise_error(CouchRest::Model::DocumentNotFound)
144
- end
145
-
146
- it "raises exception when passed an empty string " do
147
- expect { @us.find!("")}.to raise_error(CouchRest::Model::DocumentNotFound)
148
- end
149
-
150
- it "raises exception when document with provided id does not exist" do
151
- expect { @us.find!("thisisnotreallyadocumentid")}.to raise_error(CouchRest::Model::DocumentNotFound)
152
- end
153
- end
154
-
155
- # Sam Lown 2010-04-07
156
- # Removed as unclear why this should happen as before my changes
157
- # this happend by accident, not explicitly.
158
- # If requested, this feature should be added as a specific method.
159
- #
160
- #it "should clean up design docs left around on specific database" do
161
- # @us.by_title
162
- # original_id = @us.model_design_doc['_rev']
163
- # Unattached.view_by :professor
164
- # @us.by_professor
165
- # @us.model_design_doc['_rev'].should_not == original_id
166
- #end
167
- end
@@ -1,86 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe "Collections" do
4
-
5
- before(:all) do
6
- reset_test_db!
7
- titles = ["very uniq one", "really interesting", "some fun",
8
- "really awesome", "crazy bob", "this rocks", "super rad"]
9
- titles.each_with_index do |title,i|
10
- a = Article.new(:title => title, :date => Date.today)
11
- a.save
12
- end
13
-
14
- titles = ["yesterday very uniq one", "yesterday really interesting", "yesterday some fun",
15
- "yesterday really awesome", "yesterday crazy bob", "yesterday this rocks"]
16
- titles.each_with_index do |title,i|
17
- a = Article.new(:title => title, :date => Date.today - 1)
18
- a.save
19
- end
20
- end
21
- it "should return a proxy that looks like an array of 7 Article objects" do
22
- articles = Article.collection_proxy_for('Article', 'by_date', :descending => true,
23
- :key => Date.today, :include_docs => true)
24
- articles.class.should == Array
25
- articles.size.should == 7
26
- end
27
- it "should provide a class method for paginate" do
28
- articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
29
- :per_page => 3, :descending => true, :key => Date.today)
30
- articles.size.should == 3
31
-
32
- articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
33
- :per_page => 3, :page => 2, :descending => true, :key => Date.today)
34
- articles.size.should == 3
35
-
36
- articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
37
- :per_page => 3, :page => 3, :descending => true, :key => Date.today)
38
- articles.size.should == 1
39
- end
40
- it "should provide a class method for paginated_each" do
41
- options = { :design_doc => 'Article', :view_name => 'by_date',
42
- :per_page => 3, :page => 1, :descending => true, :key => Date.today }
43
- Article.paginated_each(options) do |a|
44
- a.should_not be_nil
45
- end
46
- end
47
- it "should provide a class method to get a collection for a view" do
48
- articles = Article.find_all_article_details(:key => Date.today)
49
- articles.class.should == Array
50
- articles.size.should == 7
51
- end
52
- it "should get a subset of articles using paginate" do
53
- articles = Article.collection_proxy_for('Article', 'by_date', :key => Date.today, :include_docs => true)
54
- articles.paginate(:page => 1, :per_page => 3).size.should == 3
55
- articles.paginate(:page => 2, :per_page => 3).size.should == 3
56
- articles.paginate(:page => 3, :per_page => 3).size.should == 1
57
- end
58
- it "should get all articles, a few at a time, using paginated each" do
59
- articles = Article.collection_proxy_for('Article', 'by_date', :key => Date.today, :include_docs => true)
60
- articles.paginated_each(:per_page => 3) do |a|
61
- a.should_not be_nil
62
- end
63
- end
64
-
65
- it "should raise an exception if design_doc is not provided" do
66
- lambda{Article.collection_proxy_for(nil, 'by_date')}.should raise_error
67
- lambda{Article.paginate(:view_name => 'by_date')}.should raise_error
68
- end
69
- it "should raise an exception if view_name is not provided" do
70
- lambda{Article.collection_proxy_for('Article', nil)}.should raise_error
71
- lambda{Article.paginate(:design_doc => 'Article')}.should raise_error
72
- end
73
- it "should be able to span multiple keys" do
74
- articles = Article.collection_proxy_for('Article', 'by_date', :startkey => Date.today - 1, :endkey => Date.today, :include_docs => true)
75
- articles.paginate(:page => 1, :per_page => 3).size.should == 3
76
- articles.paginate(:page => 3, :per_page => 3).size.should == 3
77
- articles.paginate(:page => 5, :per_page => 3).size.should == 1
78
- end
79
- it "should pass database parameter to pager" do
80
- proxy = mock(:proxy)
81
- proxy.stub!(:paginate)
82
- ::CouchRest::Model::Collection::CollectionProxy.should_receive(:new).with('database', anything(), anything(), anything(), anything()).and_return(proxy)
83
- Article.paginate(:design_doc => 'Article', :view_name => 'by_date', :database => 'database')
84
- end
85
-
86
- end
@@ -1,212 +0,0 @@
1
- # encoding: utf-8
2
- require 'spec_helper'
3
-
4
- describe CouchRest::Model::DesignDoc do
5
-
6
- before :all do
7
- reset_test_db!
8
- end
9
-
10
- describe "CouchRest Extension" do
11
-
12
- it "should have created a checksum! method" do
13
- ::CouchRest::Design.new.should respond_to(:checksum!)
14
- end
15
-
16
- it "should calculate a consistent checksum for model" do
17
- WithTemplateAndUniqueID.design_doc.checksum!.should eql('caa2b4c27abb82b4e37421de76d96ffc')
18
- end
19
-
20
- it "should calculate checksum for complex model" do
21
- Article.design_doc.checksum!.should eql('70dff8caea143bf40fad09adf0701104')
22
- end
23
-
24
- it "should cache the generated checksum value" do
25
- Article.design_doc.checksum!
26
- Article.design_doc['couchrest-hash'].should_not be_blank
27
- end
28
- end
29
-
30
- describe "class methods" do
31
-
32
- describe ".design_doc" do
33
- it "should provide Design document" do
34
- Article.design_doc.should be_a(::CouchRest::Design)
35
- end
36
- end
37
-
38
- describe ".design_doc_id" do
39
- it "should provide a reasonable id" do
40
- Article.design_doc_id.should eql("_design/Article")
41
- end
42
- end
43
-
44
- describe ".design_doc_slug" do
45
- it "should provide slug part of design doc" do
46
- Article.design_doc_slug.should eql('Article')
47
- end
48
- end
49
-
50
- describe ".design_doc_uri" do
51
- it "should provide complete url" do
52
- Article.design_doc_uri.should eql("#{COUCHHOST}/#{TESTDB}/_design/Article")
53
- end
54
- it "should provide complete url for new DB" do
55
- db = mock("Database")
56
- db.should_receive(:root).and_return('db')
57
- Article.design_doc_uri(db).should eql("db/_design/Article")
58
- end
59
- end
60
-
61
- describe ".stored_design_doc" do
62
- it "should load a stored design from the database" do
63
- Article.by_date
64
- Article.stored_design_doc['_rev'].should_not be_blank
65
- end
66
- it "should return nil if not already stored" do
67
- WithDefaultValues.stored_design_doc.should be_nil
68
- end
69
- end
70
-
71
- describe ".save_design_doc" do
72
- it "should call up the design updater" do
73
- Article.should_receive(:update_design_doc).with('db', false)
74
- Article.save_design_doc('db')
75
- end
76
- end
77
-
78
- describe ".save_design_doc!" do
79
- it "should call save_design_doc with force" do
80
- Article.should_receive(:save_design_doc).with('db', true)
81
- Article.save_design_doc!('db')
82
- end
83
- end
84
-
85
- end
86
-
87
- describe "basics" do
88
-
89
- before :all do
90
- reset_test_db!
91
- end
92
-
93
- it "should have been instantiated with views" do
94
- d = Article.design_doc
95
- d['views']['all']['map'].should include('Article')
96
- end
97
-
98
- it "should not have been saved yet" do
99
- lambda { Article.database.get(Article.design_doc.id) }.should raise_error(RestClient::ResourceNotFound)
100
- end
101
-
102
- describe "after requesting a view" do
103
- before :each do
104
- Article.all
105
- end
106
- it "should have saved the design doc after view request" do
107
- Article.database.get(Article.design_doc.id).should_not be_nil
108
- end
109
- end
110
-
111
- describe "model with simple views" do
112
- before(:all) do
113
- Article.all.map{|a| a.destroy(true)}
114
- Article.database.bulk_delete
115
- written_at = Time.now - 24 * 3600 * 7
116
- @titles = ["this and that", "also interesting", "more fun", "some junk"]
117
- @titles.each do |title|
118
- a = Article.new(:title => title)
119
- a.date = written_at
120
- a.save
121
- written_at += 24 * 3600
122
- end
123
- end
124
-
125
- it "will send request for the saved design doc on view request" do
126
- reset_test_db!
127
- Article.should_receive(:stored_design_doc).and_return(nil)
128
- Article.by_date
129
- end
130
-
131
- it "should have generated a design doc" do
132
- Article.design_doc["views"]["by_date"].should_not be_nil
133
- end
134
- it "should save the design doc when view requested" do
135
- Article.by_date
136
- doc = Article.database.get Article.design_doc.id
137
- doc['views']['by_date'].should_not be_nil
138
- end
139
- it "should save design doc if a view changed" do
140
- Article.by_date
141
- orig = Article.stored_design_doc
142
- design = Article.design_doc
143
- view = design['views']['by_date']['map']
144
- design['views']['by_date']['map'] = view + ' ' # little bit of white space
145
- Article.by_date
146
- Article.stored_design_doc['_rev'].should_not eql(orig['_rev'])
147
- orig['views']['by_date']['map'].should_not eql(Article.design_doc['views']['by_date']['map'])
148
- end
149
- it "should not save design doc if not changed" do
150
- Article.by_date
151
- orig = Article.stored_design_doc['_rev']
152
- Article.by_date
153
- Article.stored_design_doc['_rev'].should eql(orig)
154
- end
155
- it "should recreate the design doc if database deleted" do
156
- Article.database.recreate!
157
- lambda { Article.by_date }.should_not raise_error(RestClient::ResourceNotFound)
158
- end
159
- end
160
-
161
- describe "when auto_update_design_doc false" do
162
-
163
- before :all do
164
- Article.auto_update_design_doc = false
165
- Article.save_design_doc!
166
- end
167
-
168
- after :all do
169
- Article.auto_update_design_doc = true
170
- end
171
-
172
- it "will not send a request for the saved design doc" do
173
- Article.should_not_receive(:stored_design_doc)
174
- Article.by_date
175
- end
176
-
177
- it "will not update stored design doc if view changed" do
178
- Article.by_date
179
- orig = Article.stored_design_doc
180
- design = Article.design_doc
181
- view = design['views']['by_date']['map']
182
- design['views']['by_date']['map'] = view + ' '
183
- Article.by_date
184
- Article.stored_design_doc['_rev'].should eql(orig['_rev'])
185
- end
186
-
187
- it "will update stored design if forced" do
188
- Article.by_date
189
- orig = Article.stored_design_doc
190
- design = Article.design_doc
191
- view = design['views']['by_date']['map']
192
- design['views']['by_date']['map'] = view + ' '
193
- Article.save_design_doc!
194
- Article.stored_design_doc['_rev'].should_not eql(orig['_rev'])
195
- end
196
- end
197
- end
198
-
199
- describe "lazily refreshing the design document" do
200
- before(:all) do
201
- @db = reset_test_db!
202
- WithTemplateAndUniqueID.new('slug' => '1').save
203
- end
204
- it "should not save the design doc twice" do
205
- WithTemplateAndUniqueID.all
206
- rev = WithTemplateAndUniqueID.design_doc['_rev']
207
- WithTemplateAndUniqueID.design_doc['_rev'].should eql(rev)
208
- end
209
- end
210
-
211
-
212
- end