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