simply_stored 0.3.6 → 0.3.7
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/CHANGELOG.md +3 -0
- data/lib/simply_stored/couch/has_many.rb +10 -1
- data/lib/simply_stored/couch/has_one.rb +9 -1
- data/lib/simply_stored/instance_methods.rb +1 -1
- data/lib/simply_stored.rb +1 -1
- data/test/couchdb/couch_active_model_compatibility_test.rb +23 -0
- data/test/couchdb/couch_belongs_to_test.rb +163 -0
- data/test/couchdb/couch_conflict_handling_test.rb +96 -0
- data/test/couchdb/couch_finder_test.rb +183 -0
- data/test/couchdb/couch_has_many_test.rb +470 -0
- data/test/couchdb/couch_has_one_test.rb +135 -0
- data/test/couchdb/couch_instance_lifecycle_test.rb +240 -0
- data/test/couchdb/couch_mass_assignment_protection_test.rb +77 -0
- data/test/couchdb/couch_s3_test.rb +256 -0
- data/test/couchdb/couch_soft_deletable_test.rb +457 -0
- data/test/couchdb/couch_validations_test.rb +142 -0
- data/test/{custom_views_test.rb → couchdb/custom_views_test.rb} +3 -3
- data/test/simply_stored_simpledb_test.rb +1 -1
- metadata +28 -8
- data/test/simply_stored_couch_test.rb +0 -2111
@@ -0,0 +1,240 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../fixtures/couch')
|
3
|
+
|
4
|
+
class CouchTest < Test::Unit::TestCase
|
5
|
+
context "A simply stored couch instance" do
|
6
|
+
setup do
|
7
|
+
CouchPotato::Config.database_name = 'simply_stored_test'
|
8
|
+
recreate_db
|
9
|
+
end
|
10
|
+
|
11
|
+
context "design documents" do
|
12
|
+
should "delete all" do
|
13
|
+
db = "http://127.0.0.1:5984/#{CouchPotato::Config.database_name}"
|
14
|
+
assert_equal 0, SimplyStored::Couch.delete_all_design_documents(db)
|
15
|
+
user = User.create
|
16
|
+
Post.create(:user => user)
|
17
|
+
user.posts
|
18
|
+
assert_equal 1, SimplyStored::Couch.delete_all_design_documents(db)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when creating instances" do
|
23
|
+
should "populate the attributes" do
|
24
|
+
user = User.create(:title => "Mr.", :name => "Host Master")
|
25
|
+
assert_equal "Mr.", user.title
|
26
|
+
assert_equal "Host Master", user.name
|
27
|
+
end
|
28
|
+
|
29
|
+
should "save the instance" do
|
30
|
+
user = User.create(:title => "Mr.")
|
31
|
+
assert !user.new_record?
|
32
|
+
end
|
33
|
+
|
34
|
+
context "with a bang" do
|
35
|
+
should 'not raise an exception when saving succeeded' do
|
36
|
+
assert_nothing_raised do
|
37
|
+
User.create!(:title => "Mr.")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
should 'save the user' do
|
42
|
+
user = User.create!(:title => "Mr.")
|
43
|
+
assert !user.new_record?
|
44
|
+
end
|
45
|
+
|
46
|
+
should 'raise an error when the validations failed' do
|
47
|
+
assert_raises(CouchPotato::Database::ValidationsFailedError) do
|
48
|
+
User.create!(:title => nil)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "with a block" do
|
54
|
+
should 'call the block with the record' do
|
55
|
+
user = User.create do |u|
|
56
|
+
u.title = "Mr."
|
57
|
+
end
|
58
|
+
|
59
|
+
assert_equal "Mr.", user.title
|
60
|
+
end
|
61
|
+
|
62
|
+
should 'save the record' do
|
63
|
+
user = User.create do |u|
|
64
|
+
u.title = "Mr."
|
65
|
+
end
|
66
|
+
assert !user.new_record?
|
67
|
+
end
|
68
|
+
|
69
|
+
should 'assign attributes via the hash' do
|
70
|
+
user = User.create(:title => "Mr.") do |u|
|
71
|
+
u.name = "Host Master"
|
72
|
+
end
|
73
|
+
|
74
|
+
assert_equal "Mr.", user.title
|
75
|
+
assert_equal "Host Master", user.name
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "when saving an instance" do
|
81
|
+
should "um, save the instance" do
|
82
|
+
user = User.new(:title => "Mr.")
|
83
|
+
assert user.new_record?
|
84
|
+
user.save
|
85
|
+
assert !user.new_record?
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when using save!" do
|
89
|
+
should 'raise an exception when a validation isnt fulfilled' do
|
90
|
+
user = User.new
|
91
|
+
assert_raises(CouchPotato::Database::ValidationsFailedError) do
|
92
|
+
user.save!
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when using save(false)" do
|
98
|
+
should "not run the validations" do
|
99
|
+
user = User.new
|
100
|
+
user.save(false)
|
101
|
+
assert !user.new?
|
102
|
+
assert !user.dirty?
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when destroying an instance" do
|
108
|
+
should "remove the instance" do
|
109
|
+
user = User.create(:title => "Mr")
|
110
|
+
assert_difference 'User.find(:all).size', -1 do
|
111
|
+
user.destroy
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
should 'return the frozen instance, brrrr' do
|
116
|
+
user = User.create(:title => "Mr")
|
117
|
+
assert_equal user, user.destroy
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when updating attributes" do
|
122
|
+
should "merge in the updated attributes" do
|
123
|
+
user = User.create(:title => "Mr.")
|
124
|
+
user.update_attributes(:title => "Mrs.")
|
125
|
+
assert_equal "Mrs.", user.title
|
126
|
+
end
|
127
|
+
|
128
|
+
should "save the instance" do
|
129
|
+
user = User.create(:title => "Mr.")
|
130
|
+
user.update_attributes(:title => "Mrs.")
|
131
|
+
assert !user.dirty?
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
context "when counting" do
|
137
|
+
setup do
|
138
|
+
recreate_db
|
139
|
+
end
|
140
|
+
|
141
|
+
context "when counting all" do
|
142
|
+
should "return the number of objects in the database" do
|
143
|
+
CountMe.create(:title => "Mr.")
|
144
|
+
CountMe.create(:title => "Mrs.")
|
145
|
+
assert_equal 2, CountMe.find(:all).size
|
146
|
+
assert_equal 2, CountMe.count
|
147
|
+
end
|
148
|
+
|
149
|
+
should "only count the correct class" do
|
150
|
+
CountMe.create(:title => "Mr.")
|
151
|
+
DontCountMe.create(:title => 'Foo')
|
152
|
+
assert_equal 1, CountMe.find(:all).size
|
153
|
+
assert_equal 1, CountMe.count
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context "when counting by prefix" do
|
158
|
+
should "return the number of matching objects" do
|
159
|
+
CountMe.create(:title => "Mr.")
|
160
|
+
CountMe.create(:title => "Mrs.")
|
161
|
+
assert_equal 1, CountMe.find_all_by_title('Mr.').size
|
162
|
+
assert_equal 1, CountMe.count_by_title('Mr.')
|
163
|
+
end
|
164
|
+
|
165
|
+
should "only count the correct class" do
|
166
|
+
CountMe.create(:title => "Mr.")
|
167
|
+
DontCountMe.create(:title => 'Mr.')
|
168
|
+
assert_equal 1, CountMe.find_all_by_title('Mr.').size
|
169
|
+
assert_equal 1, CountMe.count_by_title('Mr.')
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context "when reloading an instance" do
|
175
|
+
should "reload new attributes from the database" do
|
176
|
+
user = User.create(:title => "Mr.", :name => "Host Master")
|
177
|
+
user2 = User.find(user.id)
|
178
|
+
user2.update_attributes(:title => "Mrs.", :name => "Hostess Masteress")
|
179
|
+
user.reload
|
180
|
+
assert_equal "Mrs.", user.title
|
181
|
+
assert_equal "Hostess Masteress", user.name
|
182
|
+
end
|
183
|
+
|
184
|
+
should "remove attributes that are no longer in the database" do
|
185
|
+
user = User.create(:title => "Mr.", :name => "Host Master")
|
186
|
+
assert_not_nil user.name
|
187
|
+
same_user_in_different_thread = User.find(user.id)
|
188
|
+
same_user_in_different_thread.name = nil
|
189
|
+
same_user_in_different_thread.save!
|
190
|
+
assert_nil user.reload.name
|
191
|
+
end
|
192
|
+
|
193
|
+
should "also remove foreign key attributes that are no longer in the database" do
|
194
|
+
user = User.create(:title => "Mr.", :name => "Host Master")
|
195
|
+
post = Post.create(:user => user)
|
196
|
+
assert_not_nil post.user_id
|
197
|
+
same_post_in_different_thread = Post.find(post.id)
|
198
|
+
same_post_in_different_thread.user = nil
|
199
|
+
same_post_in_different_thread.save!
|
200
|
+
assert_nil post.reload.user_id
|
201
|
+
end
|
202
|
+
|
203
|
+
should "not be dirty after reloading" do
|
204
|
+
user = User.create(:title => "Mr.", :name => "Host Master")
|
205
|
+
user2 = User.find(user.id)
|
206
|
+
user2.update_attributes(:title => "Mrs.", :name => "Hostess Masteress")
|
207
|
+
user.reload
|
208
|
+
assert !user.dirty?
|
209
|
+
end
|
210
|
+
|
211
|
+
should "ensure that association caches for has_many are cleared" do
|
212
|
+
user = User.create(:title => "Mr.", :name => "Host Master")
|
213
|
+
post = Post.create(:user => user)
|
214
|
+
assert_equal 1, user.posts.size
|
215
|
+
assert_not_nil user.instance_variable_get("@posts")
|
216
|
+
user.reload
|
217
|
+
assert_nil user.instance_variable_get("@posts")
|
218
|
+
assert_not_nil user.posts.first
|
219
|
+
end
|
220
|
+
|
221
|
+
should "ensure that association caches for belongs_to are cleared" do
|
222
|
+
user = User.create(:title => "Mr.", :name => "Host Master")
|
223
|
+
post = Post.create(:user => user)
|
224
|
+
post.user
|
225
|
+
assert_not_nil post.instance_variable_get("@user")
|
226
|
+
post.reload
|
227
|
+
assert_nil post.instance_variable_get("@user")
|
228
|
+
assert_not_nil post.user
|
229
|
+
end
|
230
|
+
|
231
|
+
should "update the revision" do
|
232
|
+
user = User.create(:title => "Mr.", :name => "Host Master")
|
233
|
+
user2 = User.find(user.id)
|
234
|
+
user2.update_attributes(:title => "Mrs.", :name => "Hostess Masteress")
|
235
|
+
user.reload
|
236
|
+
assert_equal user._rev, user2._rev
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../fixtures/couch')
|
3
|
+
|
4
|
+
class CouchMassAssignmentProtectionTest < Test::Unit::TestCase
|
5
|
+
context "attribute proctection against mass assignment" do
|
6
|
+
setup do
|
7
|
+
CouchPotato::Config.database_name = 'simply_stored_test'
|
8
|
+
recreate_db
|
9
|
+
end
|
10
|
+
|
11
|
+
context "when using attr_protected" do
|
12
|
+
setup do
|
13
|
+
Category.instance_eval do
|
14
|
+
@_accessible_attributes = []
|
15
|
+
attr_protected :parent, :alias
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
should "not allow to set with mass assignment using attributes=" do
|
20
|
+
item = Category.new
|
21
|
+
item.attributes = {:parent => 'a', :name => 'c'}
|
22
|
+
assert_equal 'c', item.name
|
23
|
+
assert_nil item.parent
|
24
|
+
end
|
25
|
+
|
26
|
+
should "not allow to set with mass assignment using attributes= - ignore string vs. symbol" do
|
27
|
+
item = Category.new
|
28
|
+
item.attributes = {'parent' => 'a', 'name' => 'c'}
|
29
|
+
assert_equal 'c', item.name
|
30
|
+
assert_nil item.parent
|
31
|
+
end
|
32
|
+
|
33
|
+
should "not allow to set with mass assignment using the constructor" do
|
34
|
+
item = Category.new(:parent => 'a', :name => 'c')
|
35
|
+
assert_equal 'c', item.name
|
36
|
+
assert_nil item.parent
|
37
|
+
end
|
38
|
+
|
39
|
+
should "not allow to set with mass assignment using update_attributes" do
|
40
|
+
item = Category.new
|
41
|
+
item.update_attributes(:parent => 'a', :name => 'c')
|
42
|
+
assert_equal 'c', item.name
|
43
|
+
assert_nil item.parent
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "attr_accessible" do
|
48
|
+
setup do
|
49
|
+
Category.instance_eval do
|
50
|
+
@_protected_attributes = []
|
51
|
+
attr_accessible :name
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
should "not allow to set with mass assignment using attributes=" do
|
56
|
+
item = Category.new
|
57
|
+
item.attributes = {:parent => 'a', :name => 'c'}
|
58
|
+
assert_equal 'c', item.name
|
59
|
+
assert_nil item.parent
|
60
|
+
end
|
61
|
+
|
62
|
+
should "not allow to set with mass assignment using the constructor" do
|
63
|
+
item = Category.new(:parent => 'a', :name => 'c')
|
64
|
+
assert_equal 'c', item.name
|
65
|
+
assert_nil item.parent
|
66
|
+
end
|
67
|
+
|
68
|
+
should "not allow to set with mass assignment using update_attributes" do
|
69
|
+
item = Category.new
|
70
|
+
item.update_attributes(:parent => 'a', :name => 'c')
|
71
|
+
# item.reload
|
72
|
+
assert_equal 'c', item.name
|
73
|
+
assert_nil item.parent
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../fixtures/couch')
|
3
|
+
|
4
|
+
class CouchS3Test < Test::Unit::TestCase
|
5
|
+
context "with s3 interaction" do
|
6
|
+
setup do
|
7
|
+
CouchPotato::Config.database_name = 'simply_stored_test'
|
8
|
+
recreate_db
|
9
|
+
CouchLogItem.instance_variable_set(:@_s3_connection, nil)
|
10
|
+
CouchLogItem._s3_options[:log_data][:ca_file] = nil
|
11
|
+
|
12
|
+
bucket = stub(:bckt) do
|
13
|
+
stubs(:put).returns(true)
|
14
|
+
stubs(:get).returns(true)
|
15
|
+
end
|
16
|
+
|
17
|
+
@bucket = bucket
|
18
|
+
|
19
|
+
@s3 = stub(:s3) do
|
20
|
+
stubs(:bucket).returns(bucket)
|
21
|
+
end
|
22
|
+
|
23
|
+
RightAws::S3.stubs(:new).returns @s3
|
24
|
+
@log_item = CouchLogItem.new
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when saving the attachment" do
|
28
|
+
should "fetch the collection" do
|
29
|
+
@log_item.log_data = "Yay! It logged!"
|
30
|
+
RightAws::S3.expects(:new).with('abcdef', 'secret!', :multi_thread => true, :ca_file => nil, :logger => nil).returns(@s3)
|
31
|
+
@log_item.save
|
32
|
+
end
|
33
|
+
|
34
|
+
should "upload the file" do
|
35
|
+
@log_item.log_data = "Yay! It logged!"
|
36
|
+
@bucket.expects(:put).with(anything, "Yay! It logged!", {}, anything)
|
37
|
+
@log_item.save
|
38
|
+
end
|
39
|
+
|
40
|
+
should "also upload on save!" do
|
41
|
+
@log_item.log_data = "Yay! It logged!"
|
42
|
+
@bucket.expects(:put).with(anything, "Yay! It logged!", {}, anything)
|
43
|
+
@log_item.save!
|
44
|
+
end
|
45
|
+
|
46
|
+
should "use the specified bucket" do
|
47
|
+
@log_item.log_data = "Yay! It logged!"
|
48
|
+
CouchLogItem._s3_options[:log_data][:bucket] = 'mybucket'
|
49
|
+
@s3.expects(:bucket).with('mybucket').returns(@bucket)
|
50
|
+
@log_item.save
|
51
|
+
end
|
52
|
+
|
53
|
+
should "create the bucket if it doesn't exist" do
|
54
|
+
@log_item.log_data = "Yay! log me"
|
55
|
+
CouchLogItem._s3_options[:log_data][:bucket] = 'mybucket'
|
56
|
+
|
57
|
+
@s3.expects(:bucket).with('mybucket').returns(nil)
|
58
|
+
@s3.expects(:bucket).with('mybucket', true, 'private', :location => nil).returns(@bucket)
|
59
|
+
@log_item.save
|
60
|
+
end
|
61
|
+
|
62
|
+
should "accept :us location option but not set it in RightAWS::S3" do
|
63
|
+
@log_item.log_data = "Yay! log me"
|
64
|
+
CouchLogItem._s3_options[:log_data][:bucket] = 'mybucket'
|
65
|
+
CouchLogItem._s3_options[:log_data][:location] = :us
|
66
|
+
|
67
|
+
@s3.expects(:bucket).with('mybucket').returns(nil)
|
68
|
+
@s3.expects(:bucket).with('mybucket', true, 'private', :location => nil).returns(@bucket)
|
69
|
+
@log_item.save
|
70
|
+
end
|
71
|
+
|
72
|
+
should "raise an error if the bucket is not ours" do
|
73
|
+
@log_item.log_data = "Yay! log me too"
|
74
|
+
CouchLogItem._s3_options[:log_data][:bucket] = 'mybucket'
|
75
|
+
CouchLogItem._s3_options[:log_data][:location] = :eu
|
76
|
+
|
77
|
+
@s3.expects(:bucket).with('mybucket').returns(nil)
|
78
|
+
@s3.expects(:bucket).with('mybucket', true, 'private', :location => :eu).raises(RightAws::AwsError, 'BucketAlreadyExists: The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again')
|
79
|
+
|
80
|
+
assert_raise(ArgumentError) do
|
81
|
+
@log_item.save
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
should "pass the logger object down to RightAws" do
|
86
|
+
logger = mock()
|
87
|
+
@log_item.log_data = "Yay! log me"
|
88
|
+
CouchLogItem._s3_options[:log_data][:bucket] = 'mybucket'
|
89
|
+
CouchLogItem._s3_options[:log_data][:logger] = logger
|
90
|
+
|
91
|
+
RightAws::S3.expects(:new).with(anything, anything, {:logger => logger, :ca_file => nil, :multi_thread => true}).returns(@s3)
|
92
|
+
@log_item.save
|
93
|
+
end
|
94
|
+
|
95
|
+
should "not upload the attachment when it hasn't been changed" do
|
96
|
+
@bucket.expects(:put).never
|
97
|
+
@log_item.save
|
98
|
+
end
|
99
|
+
|
100
|
+
should "set the permissions to private by default" do
|
101
|
+
class Item
|
102
|
+
include SimplyStored::Couch
|
103
|
+
has_s3_attachment :log_data, :bucket => 'mybucket'
|
104
|
+
end
|
105
|
+
@bucket.expects(:put).with(anything, anything, {}, 'private')
|
106
|
+
@log_item = Item.new
|
107
|
+
@log_item.log_data = 'Yay!'
|
108
|
+
@log_item.save
|
109
|
+
end
|
110
|
+
|
111
|
+
should "set the permissions to whatever's specified in the options for the attachment" do
|
112
|
+
@log_item.save
|
113
|
+
old_perms = CouchLogItem._s3_options[:log_data][:permissions]
|
114
|
+
CouchLogItem._s3_options[:log_data][:permissions] = 'public-read'
|
115
|
+
@bucket.expects(:put).with(anything, anything, {}, 'public-read')
|
116
|
+
@log_item.log_data = 'Yay!'
|
117
|
+
@log_item.save
|
118
|
+
CouchLogItem._s3_options[:log_data][:permissions] = old_perms
|
119
|
+
end
|
120
|
+
|
121
|
+
should "use the full class name and the id as key" do
|
122
|
+
@log_item.save
|
123
|
+
@bucket.expects(:put).with("couch_log_items/log_data/#{@log_item.id}", 'Yay!', {}, anything)
|
124
|
+
@log_item.log_data = 'Yay!'
|
125
|
+
@log_item.save
|
126
|
+
end
|
127
|
+
|
128
|
+
should "mark the attachment as not dirty after uploading" do
|
129
|
+
@log_item.log_data = 'Yay!'
|
130
|
+
@log_item.save
|
131
|
+
assert !@log_item.instance_variable_get(:@_s3_attachments)[:log_data][:dirty]
|
132
|
+
end
|
133
|
+
|
134
|
+
should 'store the attachment when the validations succeeded' do
|
135
|
+
@log_item.log_data = 'Yay!'
|
136
|
+
@log_item.stubs(:valid?).returns(true)
|
137
|
+
@bucket.expects(:put)
|
138
|
+
@log_item.save
|
139
|
+
end
|
140
|
+
|
141
|
+
should "not store the attachment when the validations failed" do
|
142
|
+
@log_item.log_data = 'Yay!'
|
143
|
+
@log_item.stubs(:valid?).returns(false)
|
144
|
+
@bucket.expects(:put).never
|
145
|
+
@log_item.save
|
146
|
+
end
|
147
|
+
|
148
|
+
should "save the attachment status" do
|
149
|
+
@log_item.save
|
150
|
+
@log_item.attributes["log_data_attachments"]
|
151
|
+
end
|
152
|
+
|
153
|
+
should "save generate the url for the attachment" do
|
154
|
+
@log_item._s3_options[:log_data][:bucket] = 'bucket-for-monsieur'
|
155
|
+
@log_item._s3_options[:log_data][:permissions] = 'public-read'
|
156
|
+
@log_item.save
|
157
|
+
assert_equal "http://bucket-for-monsieur.s3.amazonaws.com/#{@log_item.s3_attachment_key(:log_data)}", @log_item.log_data_url
|
158
|
+
end
|
159
|
+
|
160
|
+
should "add a short-lived access key for private attachments" do
|
161
|
+
@log_item._s3_options[:log_data][:bucket] = 'bucket-for-monsieur'
|
162
|
+
@log_item._s3_options[:log_data][:location] = :us
|
163
|
+
@log_item._s3_options[:log_data][:permissions] = 'private'
|
164
|
+
@log_item.save
|
165
|
+
assert @log_item.log_data_url.gsub("%2F", '/').include?("https://bucket-for-monsieur.s3.amazonaws.com:443/#{@log_item.s3_attachment_key(:log_data)}"), @log_item.log_data_url
|
166
|
+
assert @log_item.log_data_url.include?("Signature=")
|
167
|
+
assert @log_item.log_data_url.include?("Expires=")
|
168
|
+
end
|
169
|
+
|
170
|
+
should "serialize data other than strings to json" do
|
171
|
+
@log_item.log_data = ['one log entry', 'and another one']
|
172
|
+
@bucket.expects(:put).with(anything, '["one log entry","and another one"]', {}, anything)
|
173
|
+
@log_item.save
|
174
|
+
end
|
175
|
+
|
176
|
+
context "when noting the size of the attachment" do
|
177
|
+
should "store on upload" do
|
178
|
+
@log_item.log_data = 'abc'
|
179
|
+
@bucket.expects(:put)
|
180
|
+
assert @log_item.save
|
181
|
+
assert_equal 3, @log_item.log_data_size
|
182
|
+
end
|
183
|
+
|
184
|
+
should "update the size if the attachment gets updated" do
|
185
|
+
@log_item.log_data = 'abc'
|
186
|
+
@bucket.stubs(:put)
|
187
|
+
assert @log_item.save
|
188
|
+
assert_equal 3, @log_item.log_data_size
|
189
|
+
|
190
|
+
@log_item.log_data = 'example'
|
191
|
+
assert @log_item.save
|
192
|
+
assert_equal 7, @log_item.log_data_size
|
193
|
+
end
|
194
|
+
|
195
|
+
should "store the size of json attachments" do
|
196
|
+
@log_item.log_data = ['abc']
|
197
|
+
@bucket.stubs(:put)
|
198
|
+
assert @log_item.save
|
199
|
+
assert_equal ['abc'].to_json.size, @log_item.log_data_size
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
context "when fetching the data" do
|
205
|
+
should "create a configured S3 connection" do
|
206
|
+
CouchLogItem._s3_options[:log_data][:bucket] = 'mybucket'
|
207
|
+
CouchLogItem._s3_options[:log_data][:location] = :eu
|
208
|
+
CouchLogItem._s3_options[:log_data][:ca_file] = '/etc/ssl/ca.crt'
|
209
|
+
|
210
|
+
RightAws::S3.expects(:new).with('abcdef', 'secret!', :multi_thread => true, :ca_file => '/etc/ssl/ca.crt', :logger => nil).returns(@s3)
|
211
|
+
|
212
|
+
@log_item.log_data
|
213
|
+
end
|
214
|
+
|
215
|
+
should "fetch the data from s3 and set the attachment attribute" do
|
216
|
+
@log_item.instance_variable_set(:@_s3_attachments, {})
|
217
|
+
@bucket.expects(:get).with("couch_log_items/log_data/#{@log_item.id}").returns("Yay!")
|
218
|
+
assert_equal "Yay!", @log_item.log_data
|
219
|
+
end
|
220
|
+
|
221
|
+
should "not mark the the attachment as dirty" do
|
222
|
+
@log_item.instance_variable_set(:@_s3_attachments, {})
|
223
|
+
@bucket.expects(:get).with("couch_log_items/log_data/#{@log_item.id}").returns("Yay!")
|
224
|
+
@log_item.log_data
|
225
|
+
assert !@log_item._s3_attachments[:log_data][:dirty]
|
226
|
+
end
|
227
|
+
|
228
|
+
should "not try to fetch the attachment if the value is already set" do
|
229
|
+
@log_item.log_data = "Yay!"
|
230
|
+
@bucket.expects(:get).never
|
231
|
+
assert_equal "Yay!", @log_item.log_data
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
context "when deleting" do
|
236
|
+
setup do
|
237
|
+
CouchLogItem._s3_options[:log_data][:after_delete] = :nothing
|
238
|
+
@log_item.log_data = 'Yatzzee'
|
239
|
+
@log_item.save
|
240
|
+
end
|
241
|
+
|
242
|
+
should "do nothing to S3" do
|
243
|
+
@bucket.expects(:key).never
|
244
|
+
@log_item.delete
|
245
|
+
end
|
246
|
+
|
247
|
+
should "also delete on S3 if configured so" do
|
248
|
+
CouchLogItem._s3_options[:log_data][:after_delete] = :delete
|
249
|
+
s3_key = mock(:delete => true)
|
250
|
+
@bucket.expects(:key).with(@log_item.s3_attachment_key('log_data'), true).returns(s3_key)
|
251
|
+
@log_item.delete
|
252
|
+
end
|
253
|
+
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|