couchrest_model 1.0.0.beta7

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 (69) hide show
  1. data/LICENSE +176 -0
  2. data/README.md +320 -0
  3. data/Rakefile +71 -0
  4. data/THANKS.md +19 -0
  5. data/examples/model/example.rb +144 -0
  6. data/history.txt +180 -0
  7. data/lib/couchrest/model.rb +10 -0
  8. data/lib/couchrest/model/associations.rb +207 -0
  9. data/lib/couchrest/model/attribute_protection.rb +74 -0
  10. data/lib/couchrest/model/attributes.rb +75 -0
  11. data/lib/couchrest/model/base.rb +111 -0
  12. data/lib/couchrest/model/callbacks.rb +27 -0
  13. data/lib/couchrest/model/casted_array.rb +39 -0
  14. data/lib/couchrest/model/casted_model.rb +68 -0
  15. data/lib/couchrest/model/class_proxy.rb +122 -0
  16. data/lib/couchrest/model/collection.rb +260 -0
  17. data/lib/couchrest/model/design_doc.rb +126 -0
  18. data/lib/couchrest/model/document_queries.rb +82 -0
  19. data/lib/couchrest/model/errors.rb +23 -0
  20. data/lib/couchrest/model/extended_attachments.rb +73 -0
  21. data/lib/couchrest/model/persistence.rb +141 -0
  22. data/lib/couchrest/model/properties.rb +144 -0
  23. data/lib/couchrest/model/property.rb +96 -0
  24. data/lib/couchrest/model/support/couchrest.rb +19 -0
  25. data/lib/couchrest/model/support/hash.rb +9 -0
  26. data/lib/couchrest/model/typecast.rb +170 -0
  27. data/lib/couchrest/model/validations.rb +68 -0
  28. data/lib/couchrest/model/validations/casted_model.rb +14 -0
  29. data/lib/couchrest/model/validations/locale/en.yml +5 -0
  30. data/lib/couchrest/model/validations/uniqueness.rb +45 -0
  31. data/lib/couchrest/model/views.rb +167 -0
  32. data/lib/couchrest_model.rb +56 -0
  33. data/spec/couchrest/assocations_spec.rb +213 -0
  34. data/spec/couchrest/attachment_spec.rb +148 -0
  35. data/spec/couchrest/attribute_protection_spec.rb +153 -0
  36. data/spec/couchrest/base_spec.rb +463 -0
  37. data/spec/couchrest/casted_model_spec.rb +424 -0
  38. data/spec/couchrest/casted_spec.rb +75 -0
  39. data/spec/couchrest/class_proxy_spec.rb +132 -0
  40. data/spec/couchrest/inherited_spec.rb +40 -0
  41. data/spec/couchrest/persistence_spec.rb +409 -0
  42. data/spec/couchrest/property_spec.rb +804 -0
  43. data/spec/couchrest/subclass_spec.rb +99 -0
  44. data/spec/couchrest/validations.rb +73 -0
  45. data/spec/couchrest/view_spec.rb +463 -0
  46. data/spec/fixtures/attachments/README +3 -0
  47. data/spec/fixtures/attachments/couchdb.png +0 -0
  48. data/spec/fixtures/attachments/test.html +11 -0
  49. data/spec/fixtures/base.rb +139 -0
  50. data/spec/fixtures/more/article.rb +35 -0
  51. data/spec/fixtures/more/card.rb +17 -0
  52. data/spec/fixtures/more/cat.rb +19 -0
  53. data/spec/fixtures/more/course.rb +25 -0
  54. data/spec/fixtures/more/event.rb +8 -0
  55. data/spec/fixtures/more/invoice.rb +14 -0
  56. data/spec/fixtures/more/person.rb +9 -0
  57. data/spec/fixtures/more/question.rb +7 -0
  58. data/spec/fixtures/more/service.rb +10 -0
  59. data/spec/fixtures/more/user.rb +22 -0
  60. data/spec/fixtures/views/lib.js +3 -0
  61. data/spec/fixtures/views/test_view/lib.js +3 -0
  62. data/spec/fixtures/views/test_view/only-map.js +4 -0
  63. data/spec/fixtures/views/test_view/test-map.js +3 -0
  64. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  65. data/spec/spec.opts +5 -0
  66. data/spec/spec_helper.rb +48 -0
  67. data/utils/remap.rb +27 -0
  68. data/utils/subset.rb +30 -0
  69. metadata +232 -0
@@ -0,0 +1,56 @@
1
+
2
+ # require File.join(File.dirname(__FILE__), "couchrest", "extended_document")
3
+
4
+ gem 'couchrest'
5
+
6
+ require 'couchrest'
7
+
8
+ require 'active_support/core_ext'
9
+ require 'active_support/json'
10
+ require 'active_model'
11
+ require "active_model/callbacks"
12
+ require "active_model/conversion"
13
+ require "active_model/deprecated_error_methods"
14
+ require "active_model/errors"
15
+ require "active_model/naming"
16
+ require "active_model/serialization"
17
+ require "active_model/translation"
18
+ require "active_model/validator"
19
+ require "active_model/validations"
20
+ require 'mime/types'
21
+ require "enumerator"
22
+ require "time"
23
+ require 'digest/md5'
24
+
25
+ require 'bigdecimal' # used in typecast
26
+ require 'bigdecimal/util' # used in typecast
27
+
28
+ require 'couchrest/model'
29
+ require 'couchrest/model/errors'
30
+ require "couchrest/model/persistence"
31
+ require "couchrest/model/typecast"
32
+ require "couchrest/model/property"
33
+ require "couchrest/model/casted_array"
34
+ require "couchrest/model/properties"
35
+ require "couchrest/model/validations"
36
+ require "couchrest/model/callbacks"
37
+ require "couchrest/model/document_queries"
38
+ require "couchrest/model/views"
39
+ require "couchrest/model/design_doc"
40
+ require "couchrest/model/extended_attachments"
41
+ require "couchrest/model/class_proxy"
42
+ require "couchrest/model/collection"
43
+ require "couchrest/model/attribute_protection"
44
+ require "couchrest/model/attributes"
45
+ require "couchrest/model/associations"
46
+
47
+ # Monkey patches applied to couchrest
48
+ require "couchrest/model/support/couchrest"
49
+ require "couchrest/model/support/hash"
50
+
51
+ # Base libraries
52
+ require "couchrest/model/casted_model"
53
+ require "couchrest/model/base"
54
+
55
+ # Add rails support *after* everything has loaded
56
+
@@ -0,0 +1,213 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('../../spec_helper', __FILE__)
3
+
4
+ class Client < CouchRest::Model::Base
5
+ use_database DB
6
+
7
+ property :name
8
+ property :tax_code
9
+ end
10
+
11
+ class SaleEntry < CouchRest::Model::Base
12
+ use_database DB
13
+
14
+ property :description
15
+ property :price
16
+ end
17
+
18
+ class SaleInvoice < CouchRest::Model::Base
19
+ use_database DB
20
+
21
+ belongs_to :client
22
+ belongs_to :alternate_client, :class_name => 'Client', :foreign_key => 'alt_client_id'
23
+
24
+ collection_of :entries, :class_name => 'SaleEntry'
25
+
26
+ property :date, Date
27
+ property :price, Integer
28
+ end
29
+
30
+
31
+ describe "Assocations" do
32
+
33
+ describe "of type belongs to" do
34
+
35
+ before :each do
36
+ @invoice = SaleInvoice.create(:price => "sam", :price => 2000)
37
+ @client = Client.create(:name => "Sam Lown")
38
+ end
39
+
40
+ it "should create a foreign key property with setter and getter" do
41
+ @invoice.properties.find{|p| p.name == 'client_id'}.should_not be_nil
42
+ @invoice.respond_to?(:client_id).should be_true
43
+ @invoice.respond_to?("client_id=").should be_true
44
+ end
45
+
46
+ it "should set the property and provide object when set" do
47
+ @invoice.client = @client
48
+ @invoice.client_id.should eql(@client.id)
49
+ @invoice.client.should eql(@client)
50
+ end
51
+
52
+ it "should set the attribute, save and return" do
53
+ @invoice.client = @client
54
+ @invoice.save
55
+ @invoice = SaleInvoice.get(@invoice.id)
56
+ @invoice.client.id.should eql(@client.id)
57
+ end
58
+
59
+ it "should remove the association if nil is provided" do
60
+ @invoice.client = @client
61
+ @invoice.client = nil
62
+ @invoice.client_id.should be_nil
63
+ end
64
+
65
+ it "should not try to search for association if foreign_key is nil" do
66
+ @invoice.client_id = nil
67
+ Client.should_not_receive(:get)
68
+ @invoice.client
69
+ end
70
+
71
+ it "should raise error if class name does not exist" do
72
+ lambda {
73
+ class TestBadAssoc < CouchRest::Model::Base
74
+ belongs_to :test_bad_item
75
+ end
76
+ }.should raise_error
77
+ end
78
+
79
+ it "should allow override of foreign key" do
80
+ @invoice.respond_to?(:alternate_client).should be_true
81
+ @invoice.respond_to?("alternate_client=").should be_true
82
+ @invoice.properties.find{|p| p.name == 'alt_client_id'}.should_not be_nil
83
+ end
84
+
85
+ it "should allow override of foreign key and save" do
86
+ @invoice.alternate_client = @client
87
+ @invoice.save
88
+ @invoice = SaleInvoice.get(@invoice.id)
89
+ @invoice.alternate_client.id.should eql(@client.id)
90
+ end
91
+
92
+ end
93
+
94
+ describe "of type collection_of" do
95
+
96
+ before(:each) do
97
+ @invoice = SaleInvoice.create(:price => "sam", :price => 2000)
98
+ @entries = [
99
+ SaleEntry.create(:description => 'test line 1', :price => 500),
100
+ SaleEntry.create(:description => 'test line 2', :price => 500),
101
+ SaleEntry.create(:description => 'test line 3', :price => 1000)
102
+ ]
103
+ end
104
+
105
+ it "should create an associated property and collection proxy" do
106
+ @invoice.respond_to?('entry_ids')
107
+ @invoice.respond_to?('entry_ids=')
108
+ @invoice.entries.class.should eql(::CouchRest::CollectionOfProxy)
109
+ end
110
+
111
+ it "should allow replacement of objects" do
112
+ @invoice.entries = @entries
113
+ @invoice.entries.length.should eql(3)
114
+ @invoice.entry_ids.length.should eql(3)
115
+ @invoice.entries.first.should eql(@entries.first)
116
+ @invoice.entry_ids.first.should eql(@entries.first.id)
117
+ end
118
+
119
+ it "should allow ids to be set directly and load entries" do
120
+ @invoice.entry_ids = @entries.collect{|i| i.id}
121
+ @invoice.entries.length.should eql(3)
122
+ @invoice.entries.first.should eql(@entries.first)
123
+ end
124
+
125
+ it "should replace collection if ids replaced" do
126
+ @invoice.entry_ids = @entries.collect{|i| i.id}
127
+ @invoice.entries.length.should eql(3) # load once
128
+ @invoice.entry_ids = @entries[0..1].collect{|i| i.id}
129
+ @invoice.entries.length.should eql(2)
130
+ end
131
+
132
+ it "should allow forced collection update if ids changed" do
133
+ @invoice.entry_ids = @entries[0..1].collect{|i| i.id}
134
+ @invoice.entries.length.should eql(2) # load once
135
+ @invoice.entry_ids << @entries[2].id
136
+ @invoice.entry_ids.length.should eql(3)
137
+ @invoice.entries.length.should eql(2) # cached!
138
+ @invoice.entries(true).length.should eql(3)
139
+ end
140
+
141
+ it "should empty arrays when nil collection provided" do
142
+ @invoice.entries = @entries
143
+ @invoice.entries = nil
144
+ @invoice.entry_ids.should be_empty
145
+ @invoice.entries.should be_empty
146
+ end
147
+
148
+ it "should empty arrays when nil ids array provided" do
149
+ @invoice.entries = @entries
150
+ @invoice.entry_ids = nil
151
+ @invoice.entry_ids.should be_empty
152
+ @invoice.entries.should be_empty
153
+ end
154
+
155
+ it "should ignore nil entries" do
156
+ @invoice.entries = [ nil ]
157
+ @invoice.entry_ids.should be_empty
158
+ @invoice.entries.should be_empty
159
+ end
160
+
161
+ describe "proxy" do
162
+
163
+ it "should ensure new entries to proxy are matched" do
164
+ @invoice.entries << @entries.first
165
+ @invoice.entry_ids.first.should eql(@entries.first.id)
166
+ @invoice.entries.first.should eql(@entries.first)
167
+ @invoice.entries << @entries[1]
168
+ @invoice.entries.count.should eql(2)
169
+ @invoice.entry_ids.count.should eql(2)
170
+ @invoice.entry_ids.last.should eql(@entries[1].id)
171
+ @invoice.entries.last.should eql(@entries[1])
172
+ end
173
+
174
+ it "should support push method" do
175
+ @invoice.entries.push(@entries.first)
176
+ @invoice.entry_ids.first.should eql(@entries.first.id)
177
+ end
178
+
179
+ it "should support []= method" do
180
+ @invoice.entries[0] = @entries.first
181
+ @invoice.entry_ids.first.should eql(@entries.first.id)
182
+ end
183
+
184
+ it "should support unshift method" do
185
+ @invoice.entries.unshift(@entries.first)
186
+ @invoice.entry_ids.first.should eql(@entries.first.id)
187
+ @invoice.entries.unshift(@entries[1])
188
+ @invoice.entry_ids.first.should eql(@entries[1].id)
189
+ end
190
+
191
+ it "should support pop method" do
192
+ @invoice.entries.push(@entries.first)
193
+ @invoice.entries.pop.should eql(@entries.first)
194
+ @invoice.entries.empty?.should be_true
195
+ @invoice.entry_ids.empty?.should be_true
196
+ end
197
+
198
+ it "should support shift method" do
199
+ @invoice.entries.push(@entries[0])
200
+ @invoice.entries.push(@entries[1])
201
+ @invoice.entries.shift.should eql(@entries[0])
202
+ @invoice.entries.first.should eql(@entries[1])
203
+ @invoice.entry_ids.first.should eql(@entries[1].id)
204
+ end
205
+
206
+
207
+ end
208
+
209
+
210
+ end
211
+
212
+ end
213
+
@@ -0,0 +1,148 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "Model attachments" do
4
+
5
+ describe "#has_attachment?" do
6
+ before(:each) do
7
+ reset_test_db!
8
+ @obj = Basic.new
9
+ @obj.save.should be_true
10
+ @file = File.open(FIXTURE_PATH + '/attachments/test.html')
11
+ @attachment_name = 'my_attachment'
12
+ @obj.create_attachment(:file => @file, :name => @attachment_name)
13
+ end
14
+
15
+ it 'should return false if there is no attachment' do
16
+ @obj.has_attachment?('bogus').should be_false
17
+ end
18
+
19
+ it 'should return true if there is an attachment' do
20
+ @obj.has_attachment?(@attachment_name).should be_true
21
+ end
22
+
23
+ it 'should return true if an object with an attachment is reloaded' do
24
+ @obj.save.should be_true
25
+ reloaded_obj = Basic.get(@obj.id)
26
+ reloaded_obj.has_attachment?(@attachment_name).should be_true
27
+ end
28
+
29
+ it 'should return false if an attachment has been removed' do
30
+ @obj.delete_attachment(@attachment_name)
31
+ @obj.has_attachment?(@attachment_name).should be_false
32
+ end
33
+ end
34
+
35
+ describe "creating an attachment" do
36
+ before(:each) do
37
+ @obj = Basic.new
38
+ @obj.save.should be_true
39
+ @file_ext = File.open(FIXTURE_PATH + '/attachments/test.html')
40
+ @file_no_ext = File.open(FIXTURE_PATH + '/attachments/README')
41
+ @attachment_name = 'my_attachment'
42
+ @content_type = 'media/mp3'
43
+ end
44
+
45
+ it "should create an attachment from file with an extension" do
46
+ @obj.create_attachment(:file => @file_ext, :name => @attachment_name)
47
+ @obj.save.should be_true
48
+ reloaded_obj = Basic.get(@obj.id)
49
+ reloaded_obj['_attachments'][@attachment_name].should_not be_nil
50
+ end
51
+
52
+ it "should create an attachment from file without an extension" do
53
+ @obj.create_attachment(:file => @file_no_ext, :name => @attachment_name)
54
+ @obj.save.should be_true
55
+ reloaded_obj = Basic.get(@obj.id)
56
+ reloaded_obj['_attachments'][@attachment_name].should_not be_nil
57
+ end
58
+
59
+ it 'should raise ArgumentError if :file is missing' do
60
+ lambda{ @obj.create_attachment(:name => @attachment_name) }.should raise_error
61
+ end
62
+
63
+ it 'should raise ArgumentError if :name is missing' do
64
+ lambda{ @obj.create_attachment(:file => @file_ext) }.should raise_error
65
+ end
66
+
67
+ it 'should set the content-type if passed' do
68
+ @obj.create_attachment(:file => @file_ext, :name => @attachment_name, :content_type => @content_type)
69
+ @obj['_attachments'][@attachment_name]['content_type'].should == @content_type
70
+ end
71
+
72
+ it "should detect the content-type automatically" do
73
+ @obj.create_attachment(:file => File.open(FIXTURE_PATH + '/attachments/couchdb.png'), :name => "couchdb.png")
74
+ @obj['_attachments']['couchdb.png']['content_type'].should == "image/png"
75
+ end
76
+
77
+ it "should use name to detect the content-type automatically if no file" do
78
+ file = File.open(FIXTURE_PATH + '/attachments/couchdb.png')
79
+ file.stub!(:path).and_return("badfilname")
80
+ @obj.create_attachment(:file => File.open(FIXTURE_PATH + '/attachments/couchdb.png'), :name => "couchdb.png")
81
+ @obj['_attachments']['couchdb.png']['content_type'].should == "image/png"
82
+ end
83
+
84
+ end
85
+
86
+ describe 'reading, updating, and deleting an attachment' do
87
+ before(:each) do
88
+ @obj = Basic.new
89
+ @file = File.open(FIXTURE_PATH + '/attachments/test.html')
90
+ @attachment_name = 'my_attachment'
91
+ @obj.create_attachment(:file => @file, :name => @attachment_name)
92
+ @obj.save.should be_true
93
+ @file.rewind
94
+ @content_type = 'media/mp3'
95
+ end
96
+
97
+ it 'should read an attachment that exists' do
98
+ @obj.read_attachment(@attachment_name).should == @file.read
99
+ end
100
+
101
+ it 'should update an attachment that exists' do
102
+ file = File.open(FIXTURE_PATH + '/attachments/README')
103
+ @file.should_not == file
104
+ @obj.update_attachment(:file => file, :name => @attachment_name)
105
+ @obj.save
106
+ reloaded_obj = Basic.get(@obj.id)
107
+ file.rewind
108
+ reloaded_obj.read_attachment(@attachment_name).should_not == @file.read
109
+ reloaded_obj.read_attachment(@attachment_name).should == file.read
110
+ end
111
+
112
+ it 'should set the content-type if passed' do
113
+ file = File.open(FIXTURE_PATH + '/attachments/README')
114
+ @file.should_not == file
115
+ @obj.update_attachment(:file => file, :name => @attachment_name, :content_type => @content_type)
116
+ @obj['_attachments'][@attachment_name]['content_type'].should == @content_type
117
+ end
118
+
119
+ it 'should delete an attachment that exists' do
120
+ @obj.delete_attachment(@attachment_name)
121
+ @obj.save
122
+ lambda{Basic.get(@obj.id).read_attachment(@attachment_name)}.should raise_error
123
+ end
124
+ end
125
+
126
+ describe "#attachment_url" do
127
+ before(:each) do
128
+ @obj = Basic.new
129
+ @file = File.open(FIXTURE_PATH + '/attachments/test.html')
130
+ @attachment_name = 'my_attachment'
131
+ @obj.create_attachment(:file => @file, :name => @attachment_name)
132
+ @obj.save.should be_true
133
+ end
134
+
135
+ it 'should return nil if attachment does not exist' do
136
+ @obj.attachment_url('bogus').should be_nil
137
+ end
138
+
139
+ it 'should return the attachment URL as specified by CouchDB HttpDocumentApi' do
140
+ @obj.attachment_url(@attachment_name).should == "#{Basic.database}/#{@obj.id}/#{@attachment_name}"
141
+ end
142
+
143
+ it 'should return the attachment URI' do
144
+ @obj.attachment_uri(@attachment_name).should == "#{Basic.database.uri}/#{@obj.id}/#{@attachment_name}"
145
+ end
146
+
147
+ end
148
+ end
@@ -0,0 +1,153 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ describe "Model Attributes" do
4
+
5
+ describe "no declarations" do
6
+ class NoProtection < CouchRest::Model::Base
7
+ use_database TEST_SERVER.default_database
8
+ property :name
9
+ property :phone
10
+ end
11
+
12
+ it "should not protect anything through new" do
13
+ user = NoProtection.new(:name => "will", :phone => "555-5555")
14
+
15
+ user.name.should == "will"
16
+ user.phone.should == "555-5555"
17
+ end
18
+
19
+ it "should not protect anything through attributes=" do
20
+ user = NoProtection.new
21
+ user.attributes = {:name => "will", :phone => "555-5555"}
22
+
23
+ user.name.should == "will"
24
+ user.phone.should == "555-5555"
25
+ end
26
+
27
+ it "should recreate from the database properly" do
28
+ user = NoProtection.new
29
+ user.name = "will"
30
+ user.phone = "555-5555"
31
+ user.save!
32
+
33
+ user = NoProtection.get(user.id)
34
+ user.name.should == "will"
35
+ user.phone.should == "555-5555"
36
+ end
37
+ end
38
+
39
+ describe "Model Base", "accessible flag" do
40
+ class WithAccessible < CouchRest::Model::Base
41
+ use_database TEST_SERVER.default_database
42
+ property :name, :accessible => true
43
+ property :admin, :default => false
44
+ end
45
+
46
+ it "should recognize accessible properties" do
47
+ props = WithAccessible.accessible_properties.map { |prop| prop.name}
48
+ props.should include("name")
49
+ props.should_not include("admin")
50
+ end
51
+
52
+ it "should protect non-accessible properties set through new" do
53
+ user = WithAccessible.new(:name => "will", :admin => true)
54
+
55
+ user.name.should == "will"
56
+ user.admin.should == false
57
+ end
58
+
59
+ it "should protect non-accessible properties set through attributes=" do
60
+ user = WithAccessible.new
61
+ user.attributes = {:name => "will", :admin => true}
62
+
63
+ user.name.should == "will"
64
+ user.admin.should == false
65
+ end
66
+ end
67
+
68
+ describe "Model Base", "protected flag" do
69
+ class WithProtected < CouchRest::Model::Base
70
+ use_database TEST_SERVER.default_database
71
+ property :name
72
+ property :admin, :default => false, :protected => true
73
+ end
74
+
75
+ it "should recognize protected properties" do
76
+ props = WithProtected.protected_properties.map { |prop| prop.name}
77
+ props.should_not include("name")
78
+ props.should include("admin")
79
+ end
80
+
81
+ it "should protect non-accessible properties set through new" do
82
+ user = WithProtected.new(:name => "will", :admin => true)
83
+
84
+ user.name.should == "will"
85
+ user.admin.should == false
86
+ end
87
+
88
+ it "should protect non-accessible properties set through attributes=" do
89
+ user = WithProtected.new
90
+ user.attributes = {:name => "will", :admin => true}
91
+
92
+ user.name.should == "will"
93
+ user.admin.should == false
94
+ end
95
+ end
96
+
97
+ describe "protected flag" do
98
+ class WithBoth < CouchRest::Model::Base
99
+ use_database TEST_SERVER.default_database
100
+ property :name, :accessible => true
101
+ property :admin, :default => false, :protected => true
102
+ end
103
+
104
+ it "should raise an error when both are set" do
105
+ lambda { WithBoth.new }.should raise_error
106
+ end
107
+ end
108
+
109
+ describe "from database" do
110
+ class WithProtected < CouchRest::Model::Base
111
+ use_database TEST_SERVER.default_database
112
+ property :name
113
+ property :admin, :default => false, :protected => true
114
+ view_by :name
115
+ end
116
+
117
+ before(:each) do
118
+ @user = WithProtected.new
119
+ @user.name = "will"
120
+ @user.admin = true
121
+ @user.save!
122
+ end
123
+
124
+ def verify_attrs(user)
125
+ user.name.should == "will"
126
+ user.admin.should == true
127
+ end
128
+
129
+ it "Base#get should not strip protected attributes" do
130
+ reloaded = WithProtected.get( @user.id )
131
+ verify_attrs reloaded
132
+ end
133
+
134
+ it "Base#get! should not strip protected attributes" do
135
+ reloaded = WithProtected.get!( @user.id )
136
+ verify_attrs reloaded
137
+ end
138
+
139
+ it "Base#all should not strip protected attributes" do
140
+ # all creates a CollectionProxy
141
+ docs = WithProtected.all(:key => @user.id)
142
+ docs.size.should == 1
143
+ reloaded = docs.first
144
+ verify_attrs reloaded
145
+ end
146
+
147
+ it "views should not strip protected attributes" do
148
+ docs = WithProtected.by_name(:startkey => "will", :endkey => "will")
149
+ reloaded = docs.first
150
+ verify_attrs reloaded
151
+ end
152
+ end
153
+ end