associo 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +50 -0
- data/Gemfile +9 -0
- data/LICENSE +20 -0
- data/README.rdoc +39 -0
- data/Rakefile +12 -0
- data/associo.gemspec +25 -0
- data/lib/associo.rb +29 -0
- data/lib/associo/attachment_proxy.rb +51 -0
- data/lib/associo/class_methods.rb +64 -0
- data/lib/associo/file_helpers.rb +20 -0
- data/lib/associo/instance_methods.rb +59 -0
- data/lib/associo/io.rb +29 -0
- data/lib/associo/version.rb +3 -0
- data/specs.watchr +50 -0
- data/test/fixtures/example.m4r +0 -0
- data/test/fixtures/font.eot +0 -0
- data/test/fixtures/harmony.png +0 -0
- data/test/fixtures/mr_t.jpg +0 -0
- data/test/fixtures/test1.txt +1 -0
- data/test/fixtures/test2.txt +1 -0
- data/test/fixtures/unixref.pdf +0 -0
- data/test/helper.rb +96 -0
- data/test/joint/test_file_helpers.rb +52 -0
- data/test/joint/test_io.rb +39 -0
- data/test/test_joint.rb +554 -0
- metadata +121 -0
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
test1
|
@@ -0,0 +1 @@
|
|
1
|
+
test2
|
Binary file
|
data/test/helper.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
Bundler.setup(:default, 'test', 'development')
|
3
|
+
|
4
|
+
require 'tempfile'
|
5
|
+
require 'pp'
|
6
|
+
require 'shoulda'
|
7
|
+
require 'matchy'
|
8
|
+
require 'mocha'
|
9
|
+
require 'mongo_mapper'
|
10
|
+
|
11
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/joint')
|
12
|
+
|
13
|
+
MongoMapper.database = "testing"
|
14
|
+
|
15
|
+
class Test::Unit::TestCase
|
16
|
+
def setup
|
17
|
+
MongoMapper.database.collections.each(&:remove)
|
18
|
+
end
|
19
|
+
|
20
|
+
def assert_difference(expression, difference = 1, message = nil, &block)
|
21
|
+
b = block.send(:binding)
|
22
|
+
exps = Array.wrap(expression)
|
23
|
+
before = exps.map { |e| eval(e, b) }
|
24
|
+
yield
|
25
|
+
exps.each_with_index do |e, i|
|
26
|
+
error = "#{e.inspect} didn't change by #{difference}"
|
27
|
+
error = "#{message}.\n#{error}" if message
|
28
|
+
after = eval(e, b)
|
29
|
+
assert_equal(before[i] + difference, after, error)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def assert_no_difference(expression, message = nil, &block)
|
34
|
+
assert_difference(expression, 0, message, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def assert_grid_difference(difference=1, &block)
|
38
|
+
assert_difference("MongoMapper.database['fs.files'].find().count", difference, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def assert_no_grid_difference(&block)
|
42
|
+
assert_grid_difference(0, &block)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Asset
|
47
|
+
include MongoMapper::Document
|
48
|
+
plugin Joint
|
49
|
+
|
50
|
+
key :title, String
|
51
|
+
attachment :image
|
52
|
+
attachment :file
|
53
|
+
has_many :embedded_assets
|
54
|
+
end
|
55
|
+
|
56
|
+
class EmbeddedAsset
|
57
|
+
include MongoMapper::EmbeddedDocument
|
58
|
+
plugin Joint
|
59
|
+
|
60
|
+
key :title, String
|
61
|
+
attachment :image
|
62
|
+
attachment :file
|
63
|
+
end
|
64
|
+
|
65
|
+
class BaseModel
|
66
|
+
include MongoMapper::Document
|
67
|
+
plugin Joint
|
68
|
+
attachment :file
|
69
|
+
end
|
70
|
+
|
71
|
+
class Image < BaseModel; attachment :image end
|
72
|
+
class Video < BaseModel; attachment :video end
|
73
|
+
|
74
|
+
module JointTestHelpers
|
75
|
+
def all_files
|
76
|
+
[@file, @image, @image2, @test1, @test2]
|
77
|
+
end
|
78
|
+
|
79
|
+
def rewind_files
|
80
|
+
all_files.each { |file| file.rewind }
|
81
|
+
end
|
82
|
+
|
83
|
+
def open_file(name)
|
84
|
+
f = File.open(File.join(File.dirname(__FILE__), 'fixtures', name), 'r')
|
85
|
+
f.binmode
|
86
|
+
f
|
87
|
+
end
|
88
|
+
|
89
|
+
def grid
|
90
|
+
@grid ||= Mongo::Grid.new(MongoMapper.database)
|
91
|
+
end
|
92
|
+
|
93
|
+
def key_names
|
94
|
+
[:id, :name, :type, :size]
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class FileHelpersTest < Test::Unit::TestCase
|
4
|
+
include JointTestHelpers
|
5
|
+
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
@image = open_file('mr_t.jpg')
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
@image.close
|
13
|
+
end
|
14
|
+
|
15
|
+
context ".name" do
|
16
|
+
should "return original_filename" do
|
17
|
+
def @image.original_filename
|
18
|
+
'frank.jpg'
|
19
|
+
end
|
20
|
+
Joint::FileHelpers.name(@image).should == 'frank.jpg'
|
21
|
+
end
|
22
|
+
|
23
|
+
should "fall back to File.basename" do
|
24
|
+
Joint::FileHelpers.name(@image).should == 'mr_t.jpg'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context ".size" do
|
29
|
+
should "return size" do
|
30
|
+
def @image.size
|
31
|
+
25
|
32
|
+
end
|
33
|
+
Joint::FileHelpers.size(@image).should == 25
|
34
|
+
end
|
35
|
+
|
36
|
+
should "fall back to File.size" do
|
37
|
+
Joint::FileHelpers.size(@image).should == 13661
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context ".type" do
|
42
|
+
should "return type if Joint::Io instance" do
|
43
|
+
file = Joint::IO.new(:type => 'image/jpeg')
|
44
|
+
Joint::FileHelpers.type(@image).should == 'image/jpeg'
|
45
|
+
end
|
46
|
+
|
47
|
+
should "fall back to Wand" do
|
48
|
+
Joint::FileHelpers.type(@image).should == 'image/jpeg'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class IOTest < Test::Unit::TestCase
|
4
|
+
context "#initialize" do
|
5
|
+
should "set attributes from hash" do
|
6
|
+
Joint::IO.new(:name => 'foo').name.should == 'foo'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
should "default type to plain text" do
|
11
|
+
Joint::IO.new.type.should == 'plain/text'
|
12
|
+
end
|
13
|
+
|
14
|
+
should "default size to content size" do
|
15
|
+
content = 'This is my content'
|
16
|
+
Joint::IO.new(:content => content).size.should == content.size
|
17
|
+
end
|
18
|
+
|
19
|
+
should "alias path to name" do
|
20
|
+
Joint::IO.new(:name => 'foo').path.should == 'foo'
|
21
|
+
end
|
22
|
+
|
23
|
+
context "#read" do
|
24
|
+
should "return content" do
|
25
|
+
Joint::IO.new(:content => 'Testing').read.should == 'Testing'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "#rewind" do
|
30
|
+
should "rewinds the io to position 0" do
|
31
|
+
io = Joint::IO.new(:content => 'Testing')
|
32
|
+
io.read.should == 'Testing'
|
33
|
+
io.read.should == ''
|
34
|
+
io.rewind
|
35
|
+
io.read.should == 'Testing'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/test/test_joint.rb
ADDED
@@ -0,0 +1,554 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class JointTest < Test::Unit::TestCase
|
4
|
+
include JointTestHelpers
|
5
|
+
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
@file = open_file('unixref.pdf')
|
9
|
+
@image = open_file('mr_t.jpg')
|
10
|
+
@image2 = open_file('harmony.png')
|
11
|
+
@test1 = open_file('test1.txt')
|
12
|
+
@test2 = open_file('test2.txt')
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
all_files.each { |file| file.close }
|
17
|
+
end
|
18
|
+
|
19
|
+
context "Using Joint plugin" do
|
20
|
+
should "add each attachment to attachment_names" do
|
21
|
+
Asset.attachment_names.should == Set.new([:image, :file])
|
22
|
+
EmbeddedAsset.attachment_names.should == Set.new([:image, :file])
|
23
|
+
end
|
24
|
+
|
25
|
+
should "add keys for each attachment" do
|
26
|
+
key_names.each do |key|
|
27
|
+
Asset.keys.should include("image_#{key}")
|
28
|
+
Asset.keys.should include("file_#{key}")
|
29
|
+
EmbeddedAsset.keys.should include("image_#{key}")
|
30
|
+
EmbeddedAsset.keys.should include("file_#{key}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
should "add memoized accessors module" do
|
35
|
+
Asset.attachment_accessor_module.should be_instance_of(Module)
|
36
|
+
EmbeddedAsset.attachment_accessor_module.should be_instance_of(Module)
|
37
|
+
end
|
38
|
+
|
39
|
+
context "with inheritance" do
|
40
|
+
should "add attachment to attachment_names" do
|
41
|
+
BaseModel.attachment_names.should == Set.new([:file])
|
42
|
+
end
|
43
|
+
|
44
|
+
should "inherit attachments from superclass, but not share other inherited class attachments" do
|
45
|
+
Image.attachment_names.should == Set.new([:file, :image])
|
46
|
+
Video.attachment_names.should == Set.new([:file, :video])
|
47
|
+
end
|
48
|
+
|
49
|
+
should "add inherit keys from superclass" do
|
50
|
+
key_names.each do |key|
|
51
|
+
BaseModel.keys.should include("file_#{key}")
|
52
|
+
Image.keys.should include("file_#{key}")
|
53
|
+
Image.keys.should include("image_#{key}")
|
54
|
+
Video.keys.should include("file_#{key}")
|
55
|
+
Video.keys.should include("video_#{key}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "Assigning new attachments to document" do
|
62
|
+
setup do
|
63
|
+
@doc = Asset.create(:image => @image, :file => @file)
|
64
|
+
rewind_files
|
65
|
+
end
|
66
|
+
subject { @doc }
|
67
|
+
|
68
|
+
should "assign GridFS content_type" do
|
69
|
+
grid.get(subject.image_id).content_type.should == 'image/jpeg'
|
70
|
+
grid.get(subject.file_id).content_type.should == 'application/pdf'
|
71
|
+
end
|
72
|
+
|
73
|
+
should "assign joint keys" do
|
74
|
+
subject.image_size.should == 13661
|
75
|
+
subject.file_size.should == 68926
|
76
|
+
|
77
|
+
subject.image_type.should == "image/jpeg"
|
78
|
+
subject.file_type.should == "application/pdf"
|
79
|
+
|
80
|
+
subject.image_id.should_not be_nil
|
81
|
+
subject.file_id.should_not be_nil
|
82
|
+
|
83
|
+
subject.image_id.should be_instance_of(BSON::ObjectId)
|
84
|
+
subject.file_id.should be_instance_of(BSON::ObjectId)
|
85
|
+
end
|
86
|
+
|
87
|
+
should "allow accessing keys through attachment proxy" do
|
88
|
+
subject.image.size.should == 13661
|
89
|
+
subject.file.size.should == 68926
|
90
|
+
|
91
|
+
subject.image.type.should == "image/jpeg"
|
92
|
+
subject.file.type.should == "application/pdf"
|
93
|
+
|
94
|
+
subject.image.id.should_not be_nil
|
95
|
+
subject.file.id.should_not be_nil
|
96
|
+
|
97
|
+
subject.image.id.should be_instance_of(BSON::ObjectId)
|
98
|
+
subject.file.id.should be_instance_of(BSON::ObjectId)
|
99
|
+
end
|
100
|
+
|
101
|
+
should "proxy unknown methods to GridIO object" do
|
102
|
+
subject.image.files_id.should == subject.image_id
|
103
|
+
subject.image.content_type.should == 'image/jpeg'
|
104
|
+
subject.image.filename.should == 'mr_t.jpg'
|
105
|
+
subject.image.file_length.should == 13661
|
106
|
+
end
|
107
|
+
|
108
|
+
should "assign file name from path if original file name not available" do
|
109
|
+
subject.image_name.should == 'mr_t.jpg'
|
110
|
+
subject.file_name.should == 'unixref.pdf'
|
111
|
+
end
|
112
|
+
|
113
|
+
should "save attachment contents correctly" do
|
114
|
+
subject.file.read.should == @file.read
|
115
|
+
subject.image.read.should == @image.read
|
116
|
+
end
|
117
|
+
|
118
|
+
should "know that attachment exists" do
|
119
|
+
subject.image?.should be(true)
|
120
|
+
subject.file?.should be(true)
|
121
|
+
end
|
122
|
+
|
123
|
+
should "respond with false when asked if the attachment is blank?" do
|
124
|
+
subject.image.blank?.should be(false)
|
125
|
+
subject.file.blank?.should be(false)
|
126
|
+
end
|
127
|
+
|
128
|
+
should "clear assigned attachments so they don't get uploaded twice" do
|
129
|
+
Mongo::Grid.any_instance.expects(:put).never
|
130
|
+
subject.save
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "Assigning new attachments to embedded document" do
|
135
|
+
setup do
|
136
|
+
@asset = Asset.new
|
137
|
+
@doc = @asset.embedded_assets.build(:image => @image, :file => @file)
|
138
|
+
@asset.save!
|
139
|
+
rewind_files
|
140
|
+
end
|
141
|
+
subject { @doc }
|
142
|
+
|
143
|
+
should "assign GridFS content_type" do
|
144
|
+
grid.get(subject.image_id).content_type.should == 'image/jpeg'
|
145
|
+
grid.get(subject.file_id).content_type.should == 'application/pdf'
|
146
|
+
end
|
147
|
+
|
148
|
+
should "assign joint keys" do
|
149
|
+
subject.image_size.should == 13661
|
150
|
+
subject.file_size.should == 68926
|
151
|
+
|
152
|
+
subject.image_type.should == "image/jpeg"
|
153
|
+
subject.file_type.should == "application/pdf"
|
154
|
+
|
155
|
+
subject.image_id.should_not be_nil
|
156
|
+
subject.file_id.should_not be_nil
|
157
|
+
|
158
|
+
subject.image_id.should be_instance_of(BSON::ObjectId)
|
159
|
+
subject.file_id.should be_instance_of(BSON::ObjectId)
|
160
|
+
end
|
161
|
+
|
162
|
+
should "allow accessing keys through attachment proxy" do
|
163
|
+
subject.image.size.should == 13661
|
164
|
+
subject.file.size.should == 68926
|
165
|
+
|
166
|
+
subject.image.type.should == "image/jpeg"
|
167
|
+
subject.file.type.should == "application/pdf"
|
168
|
+
|
169
|
+
subject.image.id.should_not be_nil
|
170
|
+
subject.file.id.should_not be_nil
|
171
|
+
|
172
|
+
subject.image.id.should be_instance_of(BSON::ObjectId)
|
173
|
+
subject.file.id.should be_instance_of(BSON::ObjectId)
|
174
|
+
end
|
175
|
+
|
176
|
+
should "proxy unknown methods to GridIO object" do
|
177
|
+
subject.image.files_id.should == subject.image_id
|
178
|
+
subject.image.content_type.should == 'image/jpeg'
|
179
|
+
subject.image.filename.should == 'mr_t.jpg'
|
180
|
+
subject.image.file_length.should == 13661
|
181
|
+
end
|
182
|
+
|
183
|
+
should "assign file name from path if original file name not available" do
|
184
|
+
subject.image_name.should == 'mr_t.jpg'
|
185
|
+
subject.file_name.should == 'unixref.pdf'
|
186
|
+
end
|
187
|
+
|
188
|
+
should "save attachment contents correctly" do
|
189
|
+
subject.file.read.should == @file.read
|
190
|
+
subject.image.read.should == @image.read
|
191
|
+
end
|
192
|
+
|
193
|
+
should "know that attachment exists" do
|
194
|
+
subject.image?.should be(true)
|
195
|
+
subject.file?.should be(true)
|
196
|
+
end
|
197
|
+
|
198
|
+
should "respond with false when asked if the attachment is blank?" do
|
199
|
+
subject.image.blank?.should be(false)
|
200
|
+
subject.file.blank?.should be(false)
|
201
|
+
end
|
202
|
+
|
203
|
+
should "clear assigned attachments so they don't get uploaded twice" do
|
204
|
+
Mongo::Grid.any_instance.expects(:put).never
|
205
|
+
subject.save
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context "Updating existing attachment" do
|
210
|
+
setup do
|
211
|
+
@doc = Asset.create(:file => @test1)
|
212
|
+
assert_no_grid_difference do
|
213
|
+
@doc.file = @test2
|
214
|
+
@doc.save!
|
215
|
+
end
|
216
|
+
rewind_files
|
217
|
+
end
|
218
|
+
subject { @doc }
|
219
|
+
|
220
|
+
should "not change attachment id" do
|
221
|
+
subject.file_id_changed?.should be(false)
|
222
|
+
end
|
223
|
+
|
224
|
+
should "update keys" do
|
225
|
+
subject.file_name.should == 'test2.txt'
|
226
|
+
subject.file_type.should == "text/plain"
|
227
|
+
subject.file_size.should == 5
|
228
|
+
end
|
229
|
+
|
230
|
+
should "update GridFS" do
|
231
|
+
grid.get(subject.file_id).filename.should == 'test2.txt'
|
232
|
+
grid.get(subject.file_id).content_type.should == 'text/plain'
|
233
|
+
grid.get(subject.file_id).file_length.should == 5
|
234
|
+
grid.get(subject.file_id).read.should == @test2.read
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
context "Updating existing attachment in embedded document" do
|
239
|
+
setup do
|
240
|
+
@asset = Asset.new
|
241
|
+
@doc = @asset.embedded_assets.build(:file => @test1)
|
242
|
+
@asset.save!
|
243
|
+
assert_no_grid_difference do
|
244
|
+
@doc.file = @test2
|
245
|
+
@doc.save!
|
246
|
+
end
|
247
|
+
rewind_files
|
248
|
+
end
|
249
|
+
subject { @doc }
|
250
|
+
|
251
|
+
should "update keys" do
|
252
|
+
subject.file_name.should == 'test2.txt'
|
253
|
+
subject.file_type.should == "text/plain"
|
254
|
+
subject.file_size.should == 5
|
255
|
+
end
|
256
|
+
|
257
|
+
should "update GridFS" do
|
258
|
+
grid.get(subject.file_id).filename.should == 'test2.txt'
|
259
|
+
grid.get(subject.file_id).content_type.should == 'text/plain'
|
260
|
+
grid.get(subject.file_id).file_length.should == 5
|
261
|
+
grid.get(subject.file_id).read.should == @test2.read
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
context "Updating document but not attachments" do
|
266
|
+
setup do
|
267
|
+
@doc = Asset.create(:image => @image)
|
268
|
+
@doc.update_attributes(:title => 'Updated')
|
269
|
+
@doc.reload
|
270
|
+
rewind_files
|
271
|
+
end
|
272
|
+
subject { @doc }
|
273
|
+
|
274
|
+
should "not affect attachment" do
|
275
|
+
subject.image.read.should == @image.read
|
276
|
+
end
|
277
|
+
|
278
|
+
should "update document attributes" do
|
279
|
+
subject.title.should == 'Updated'
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context "Updating embedded document but not attachments" do
|
284
|
+
setup do
|
285
|
+
@asset = Asset.new
|
286
|
+
@doc = @asset.embedded_assets.build(:image => @image)
|
287
|
+
@doc.update_attributes(:title => 'Updated')
|
288
|
+
@asset.reload
|
289
|
+
@doc = @asset.embedded_assets.first
|
290
|
+
rewind_files
|
291
|
+
end
|
292
|
+
subject { @doc }
|
293
|
+
|
294
|
+
should "not affect attachment" do
|
295
|
+
subject.image.read.should == @image.read
|
296
|
+
end
|
297
|
+
|
298
|
+
should "update document attributes" do
|
299
|
+
subject.title.should == 'Updated'
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
context "Assigning file where file pointer is not at beginning" do
|
304
|
+
setup do
|
305
|
+
@image.read
|
306
|
+
@doc = Asset.create(:image => @image)
|
307
|
+
@doc.reload
|
308
|
+
rewind_files
|
309
|
+
end
|
310
|
+
subject { @doc }
|
311
|
+
|
312
|
+
should "rewind and correctly store contents" do
|
313
|
+
subject.image.read.should == @image.read
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
context "Setting attachment to nil" do
|
318
|
+
setup do
|
319
|
+
@doc = Asset.create(:image => @image)
|
320
|
+
rewind_files
|
321
|
+
end
|
322
|
+
subject { @doc }
|
323
|
+
|
324
|
+
should "delete attachment after save" do
|
325
|
+
assert_no_grid_difference { subject.image = nil }
|
326
|
+
assert_grid_difference(-1) { subject.save }
|
327
|
+
end
|
328
|
+
|
329
|
+
should "know that the attachment has been nullified" do
|
330
|
+
subject.image = nil
|
331
|
+
subject.image?.should be(false)
|
332
|
+
end
|
333
|
+
|
334
|
+
should "respond with true when asked if the attachment is nil?" do
|
335
|
+
subject.image = nil
|
336
|
+
subject.image.nil?.should be(true)
|
337
|
+
end
|
338
|
+
|
339
|
+
should "respond with true when asked if the attachment is blank?" do
|
340
|
+
subject.image = nil
|
341
|
+
subject.image.blank?.should be(true)
|
342
|
+
end
|
343
|
+
|
344
|
+
should "clear nil attachments after save and not attempt to delete again" do
|
345
|
+
Mongo::Grid.any_instance.expects(:delete).once
|
346
|
+
subject.image = nil
|
347
|
+
subject.save
|
348
|
+
Mongo::Grid.any_instance.expects(:delete).never
|
349
|
+
subject.save
|
350
|
+
end
|
351
|
+
|
352
|
+
should "clear id, name, type, size" do
|
353
|
+
subject.image = nil
|
354
|
+
subject.save
|
355
|
+
assert_nil subject.image_id
|
356
|
+
assert_nil subject.image_name
|
357
|
+
assert_nil subject.image_type
|
358
|
+
assert_nil subject.image_size
|
359
|
+
subject.reload
|
360
|
+
assert_nil subject.image_id
|
361
|
+
assert_nil subject.image_name
|
362
|
+
assert_nil subject.image_type
|
363
|
+
assert_nil subject.image_size
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
context "Setting attachment to nil on embedded document" do
|
368
|
+
setup do
|
369
|
+
@asset = Asset.new
|
370
|
+
@doc = @asset.embedded_assets.build(:image => @image)
|
371
|
+
@asset.save!
|
372
|
+
rewind_files
|
373
|
+
end
|
374
|
+
subject { @doc }
|
375
|
+
|
376
|
+
should "delete attachment after save" do
|
377
|
+
assert_no_grid_difference { subject.image = nil }
|
378
|
+
assert_grid_difference(-1) { subject.save }
|
379
|
+
end
|
380
|
+
|
381
|
+
should "know that the attachment has been nullified" do
|
382
|
+
subject.image = nil
|
383
|
+
subject.image?.should be(false)
|
384
|
+
end
|
385
|
+
|
386
|
+
should "respond with true when asked if the attachment is nil?" do
|
387
|
+
subject.image = nil
|
388
|
+
subject.image.nil?.should be(true)
|
389
|
+
end
|
390
|
+
|
391
|
+
should "respond with true when asked if the attachment is blank?" do
|
392
|
+
subject.image = nil
|
393
|
+
subject.image.blank?.should be(true)
|
394
|
+
end
|
395
|
+
|
396
|
+
should "clear nil attachments after save and not attempt to delete again" do
|
397
|
+
Mongo::Grid.any_instance.expects(:delete).once
|
398
|
+
subject.image = nil
|
399
|
+
subject.save
|
400
|
+
Mongo::Grid.any_instance.expects(:delete).never
|
401
|
+
subject.save
|
402
|
+
end
|
403
|
+
|
404
|
+
should "clear id, name, type, size" do
|
405
|
+
subject.image = nil
|
406
|
+
subject.save
|
407
|
+
assert_nil subject.image_id
|
408
|
+
assert_nil subject.image_name
|
409
|
+
assert_nil subject.image_type
|
410
|
+
assert_nil subject.image_size
|
411
|
+
s = subject._root_document.reload.embedded_assets.first
|
412
|
+
assert_nil s.image_id
|
413
|
+
assert_nil s.image_name
|
414
|
+
assert_nil s.image_type
|
415
|
+
assert_nil s.image_size
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
context "Retrieving attachment that does not exist" do
|
420
|
+
setup do
|
421
|
+
@doc = Asset.create
|
422
|
+
rewind_files
|
423
|
+
end
|
424
|
+
subject { @doc }
|
425
|
+
|
426
|
+
should "know that the attachment is not present" do
|
427
|
+
subject.image?.should be(false)
|
428
|
+
end
|
429
|
+
|
430
|
+
should "respond with true when asked if the attachment is nil?" do
|
431
|
+
subject.image.nil?.should be(true)
|
432
|
+
end
|
433
|
+
|
434
|
+
should "raise Mongo::GridFileNotFound" do
|
435
|
+
assert_raises(Mongo::GridFileNotFound) { subject.image.read }
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
context "Destroying a document" do
|
440
|
+
setup do
|
441
|
+
@doc = Asset.create(:image => @image)
|
442
|
+
rewind_files
|
443
|
+
end
|
444
|
+
subject { @doc }
|
445
|
+
|
446
|
+
should "remove files from grid fs as well" do
|
447
|
+
assert_grid_difference(-1) { subject.destroy }
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
context "Destroying an embedded document's _root_document" do
|
452
|
+
setup do
|
453
|
+
@asset = Asset.new
|
454
|
+
@doc = @asset.embedded_assets.build(:image => @image)
|
455
|
+
@doc.save!
|
456
|
+
rewind_files
|
457
|
+
end
|
458
|
+
subject { @doc }
|
459
|
+
|
460
|
+
should "remove files from grid fs as well" do
|
461
|
+
assert_grid_difference(-1) { subject._root_document.destroy }
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
# What about when an embedded document is removed?
|
466
|
+
|
467
|
+
context "Assigning file name" do
|
468
|
+
should "default to path" do
|
469
|
+
Asset.create(:image => @image).image.name.should == 'mr_t.jpg'
|
470
|
+
end
|
471
|
+
|
472
|
+
should "use original_filename if available" do
|
473
|
+
def @image.original_filename
|
474
|
+
'testing.txt'
|
475
|
+
end
|
476
|
+
doc = Asset.create(:image => @image)
|
477
|
+
assert_equal 'testing.txt', doc.image_name
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
context "Validating attachment presence" do
|
482
|
+
setup do
|
483
|
+
@model_class = Class.new do
|
484
|
+
include MongoMapper::Document
|
485
|
+
plugin Joint
|
486
|
+
attachment :file, :required => true
|
487
|
+
|
488
|
+
def self.name; "Foo"; end
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
should "work" do
|
493
|
+
model = @model_class.new
|
494
|
+
model.should_not be_valid
|
495
|
+
|
496
|
+
model.file = @file
|
497
|
+
model.should be_valid
|
498
|
+
|
499
|
+
model.file = nil
|
500
|
+
model.should_not be_valid
|
501
|
+
|
502
|
+
model.file = @image
|
503
|
+
model.should be_valid
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
context "Assigning joint io instance" do
|
508
|
+
setup do
|
509
|
+
io = Joint::IO.new({
|
510
|
+
:name => 'foo.txt',
|
511
|
+
:type => 'plain/text',
|
512
|
+
:content => 'This is my stuff'
|
513
|
+
})
|
514
|
+
@asset = Asset.create(:file => io)
|
515
|
+
end
|
516
|
+
|
517
|
+
should "work" do
|
518
|
+
@asset.file_name.should == 'foo.txt'
|
519
|
+
@asset.file_size.should == 16
|
520
|
+
@asset.file_type.should == 'plain/text'
|
521
|
+
@asset.file.read.should == 'This is my stuff'
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
context "A font file" do
|
526
|
+
setup do
|
527
|
+
@file = open_file('font.eot')
|
528
|
+
@doc = Asset.create(:file => @file)
|
529
|
+
end
|
530
|
+
subject { @doc }
|
531
|
+
|
532
|
+
should "assign joint keys" do
|
533
|
+
subject.file_size.should == 17610
|
534
|
+
subject.file_type.should == "application/octet-stream"
|
535
|
+
subject.file_id.should_not be_nil
|
536
|
+
subject.file_id.should be_instance_of(BSON::ObjectId)
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
context "A music file" do
|
541
|
+
setup do
|
542
|
+
@file = open_file('example.m4r')
|
543
|
+
@doc = Asset.create(:file => @file)
|
544
|
+
end
|
545
|
+
subject { @doc }
|
546
|
+
|
547
|
+
should "assign joint keys" do
|
548
|
+
subject.file_size.should == 50790
|
549
|
+
subject.file_type.should == "audio/mp4"
|
550
|
+
subject.file_id.should_not be_nil
|
551
|
+
subject.file_id.should be_instance_of(BSON::ObjectId)
|
552
|
+
end
|
553
|
+
end
|
554
|
+
end
|