joint 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -5,3 +5,4 @@ doc/*
5
5
  pkg/*
6
6
  .bundle
7
7
  *.swp
8
+ Gemfile.lock
data/Gemfile CHANGED
@@ -2,6 +2,7 @@ source :rubygems
2
2
 
3
3
  gemspec
4
4
 
5
+ gem 'rake'
5
6
  gem 'bson_ext', :require => false
6
7
  gem 'shoulda'
7
8
  gem 'mocha'
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
 
13
13
  s.add_dependency 'wand', '~> 0.4'
14
14
  s.add_dependency 'mime-types'
15
- s.add_dependency 'mongo_mapper', '~> 0.9.0'
15
+ s.add_dependency 'mongo_mapper', '~> 0.9'
16
16
 
17
17
  s.files = `git ls-files`.split("\n")
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -11,6 +11,7 @@ module Joint
11
11
  self.attachment_names = attachment_names.dup.add(name)
12
12
 
13
13
  after_save :save_attachments
14
+ before_save :nullify_nil_attachments_attributes
14
15
  after_save :destroy_nil_attachments
15
16
  before_destroy :destroy_all_attachments
16
17
 
@@ -27,12 +28,12 @@ module Joint
27
28
  end
28
29
 
29
30
  def #{name}?
30
- !nil_attachments.include?(:#{name}) && send(:#{name}_id?)
31
+ !nil_attachments.has_key?(:#{name}) && send(:#{name}_id?)
31
32
  end
32
33
 
33
34
  def #{name}=(file)
34
35
  if file.nil?
35
- nil_attachments << :#{name}
36
+ nil_attachments[:#{name}] = send("#{name}_id")
36
37
  assigned_attachments.delete(:#{name})
37
38
  else
38
39
  send("#{name}_id=", BSON::ObjectId.new) if send("#{name}_id").nil?
@@ -10,7 +10,7 @@ module Joint
10
10
  end
11
11
 
12
12
  def nil_attachments
13
- @nil_attachments ||= Set.new
13
+ @nil_attachments ||= {}
14
14
  end
15
15
 
16
16
  # IO must respond to read and rewind
@@ -27,21 +27,19 @@ module Joint
27
27
  end
28
28
  assigned_attachments.clear
29
29
  end
30
-
31
- def destroy_nil_attachments
32
- # currently MM does not send sets to instance as well
33
- nil_attachments.each do |name|
34
- grid.delete(send(name).id)
30
+
31
+ def nullify_nil_attachments_attributes
32
+ nil_attachments.each_key do |name|
35
33
  send(:"#{name}_id=", nil)
36
34
  send(:"#{name}_size=", nil)
37
35
  send(:"#{name}_type=", nil)
38
36
  send(:"#{name}_name=", nil)
39
- set({
40
- :"#{name}_id" => nil,
41
- :"#{name}_size" => nil,
42
- :"#{name}_type" => nil,
43
- :"#{name}_name" => nil,
44
- })
37
+ end
38
+ end
39
+
40
+ def destroy_nil_attachments
41
+ nil_attachments.each_value do |id|
42
+ grid.delete(id)
45
43
  end
46
44
 
47
45
  nil_attachments.clear
@@ -1,3 +1,3 @@
1
1
  module Joint
2
- Version = '0.6.0'
2
+ Version = '0.6.1'
3
3
  end
@@ -25,7 +25,8 @@ class Test::Unit::TestCase
25
25
  exps.each_with_index do |e, i|
26
26
  error = "#{e.inspect} didn't change by #{difference}"
27
27
  error = "#{message}.\n#{error}" if message
28
- assert_equal(before[i] + difference, eval(e, b), error)
28
+ after = eval(e, b)
29
+ assert_equal(before[i] + difference, after, error)
29
30
  end
30
31
  end
31
32
 
@@ -46,6 +47,16 @@ class Asset
46
47
  include MongoMapper::Document
47
48
  plugin Joint
48
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
+
49
60
  key :title, String
50
61
  attachment :image
51
62
  attachment :file
@@ -56,17 +56,21 @@ class JointTest < Test::Unit::TestCase
56
56
  context "Using Joint plugin" do
57
57
  should "add each attachment to attachment_names" do
58
58
  Asset.attachment_names.should == Set.new([:image, :file])
59
+ EmbeddedAsset.attachment_names.should == Set.new([:image, :file])
59
60
  end
60
61
 
61
62
  should "add keys for each attachment" do
62
63
  key_names.each do |key|
63
64
  Asset.keys.should include("image_#{key}")
64
65
  Asset.keys.should include("file_#{key}")
66
+ EmbeddedAsset.keys.should include("image_#{key}")
67
+ EmbeddedAsset.keys.should include("file_#{key}")
65
68
  end
66
69
  end
67
70
 
68
71
  should "add memoized accessors module" do
69
72
  Asset.attachment_accessor_module.should be_instance_of(Module)
73
+ EmbeddedAsset.attachment_accessor_module.should be_instance_of(Module)
70
74
  end
71
75
 
72
76
  context "with inheritance" do
@@ -153,9 +157,79 @@ class JointTest < Test::Unit::TestCase
153
157
  subject.file?.should be(true)
154
158
  end
155
159
 
156
- should "respond with false when asked if the attachment is nil?" do
157
- subject.image.nil?.should be(false)
158
- subject.file.nil?.should be(false)
160
+ should "respond with false when asked if the attachment is blank?" do
161
+ subject.image.blank?.should be(false)
162
+ subject.file.blank?.should be(false)
163
+ end
164
+
165
+ should "clear assigned attachments so they don't get uploaded twice" do
166
+ Mongo::Grid.any_instance.expects(:put).never
167
+ subject.save
168
+ end
169
+ end
170
+
171
+ context "Assigning new attachments to embedded document" do
172
+ setup do
173
+ @asset = Asset.new
174
+ @doc = @asset.embedded_assets.build(:image => @image, :file => @file)
175
+ @asset.save!
176
+ rewind_files
177
+ end
178
+ subject { @doc }
179
+
180
+ should "assign GridFS content_type" do
181
+ grid.get(subject.image_id).content_type.should == 'image/jpeg'
182
+ grid.get(subject.file_id).content_type.should == 'application/pdf'
183
+ end
184
+
185
+ should "assign joint keys" do
186
+ subject.image_size.should == 13661
187
+ subject.file_size.should == 68926
188
+
189
+ subject.image_type.should == "image/jpeg"
190
+ subject.file_type.should == "application/pdf"
191
+
192
+ subject.image_id.should_not be_nil
193
+ subject.file_id.should_not be_nil
194
+
195
+ subject.image_id.should be_instance_of(BSON::ObjectId)
196
+ subject.file_id.should be_instance_of(BSON::ObjectId)
197
+ end
198
+
199
+ should "allow accessing keys through attachment proxy" do
200
+ subject.image.size.should == 13661
201
+ subject.file.size.should == 68926
202
+
203
+ subject.image.type.should == "image/jpeg"
204
+ subject.file.type.should == "application/pdf"
205
+
206
+ subject.image.id.should_not be_nil
207
+ subject.file.id.should_not be_nil
208
+
209
+ subject.image.id.should be_instance_of(BSON::ObjectId)
210
+ subject.file.id.should be_instance_of(BSON::ObjectId)
211
+ end
212
+
213
+ should "proxy unknown methods to GridIO object" do
214
+ subject.image.files_id.should == subject.image_id
215
+ subject.image.content_type.should == 'image/jpeg'
216
+ subject.image.filename.should == 'mr_t.jpg'
217
+ subject.image.file_length.should == 13661
218
+ end
219
+
220
+ should "assign file name from path if original file name not available" do
221
+ subject.image_name.should == 'mr_t.jpg'
222
+ subject.file_name.should == 'unixref.pdf'
223
+ end
224
+
225
+ should "save attachment contents correctly" do
226
+ subject.file.read.should == @file.read
227
+ subject.image.read.should == @image.read
228
+ end
229
+
230
+ should "know that attachment exists" do
231
+ subject.image?.should be(true)
232
+ subject.file?.should be(true)
159
233
  end
160
234
 
161
235
  should "respond with false when asked if the attachment is blank?" do
@@ -198,6 +272,33 @@ class JointTest < Test::Unit::TestCase
198
272
  end
199
273
  end
200
274
 
275
+ context "Updating existing attachment in embedded document" do
276
+ setup do
277
+ @asset = Asset.new
278
+ @doc = @asset.embedded_assets.build(:file => @test1)
279
+ @asset.save!
280
+ assert_no_grid_difference do
281
+ @doc.file = @test2
282
+ @doc.save!
283
+ end
284
+ rewind_files
285
+ end
286
+ subject { @doc }
287
+
288
+ should "update keys" do
289
+ subject.file_name.should == 'test2.txt'
290
+ subject.file_type.should == "text/plain"
291
+ subject.file_size.should == 5
292
+ end
293
+
294
+ should "update GridFS" do
295
+ grid.get(subject.file_id).filename.should == 'test2.txt'
296
+ grid.get(subject.file_id).content_type.should == 'text/plain'
297
+ grid.get(subject.file_id).file_length.should == 5
298
+ grid.get(subject.file_id).read.should == @test2.read
299
+ end
300
+ end
301
+
201
302
  context "Updating document but not attachments" do
202
303
  setup do
203
304
  @doc = Asset.create(:image => @image)
@@ -216,6 +317,26 @@ class JointTest < Test::Unit::TestCase
216
317
  end
217
318
  end
218
319
 
320
+ context "Updating embedded document but not attachments" do
321
+ setup do
322
+ @asset = Asset.new
323
+ @doc = @asset.embedded_assets.build(:image => @image)
324
+ @doc.update_attributes(:title => 'Updated')
325
+ @asset.reload
326
+ @doc = @asset.embedded_assets.first
327
+ rewind_files
328
+ end
329
+ subject { @doc }
330
+
331
+ should "not affect attachment" do
332
+ subject.image.read.should == @image.read
333
+ end
334
+
335
+ should "update document attributes" do
336
+ subject.title.should == 'Updated'
337
+ end
338
+ end
339
+
219
340
  context "Assigning file where file pointer is not at beginning" do
220
341
  setup do
221
342
  @image.read
@@ -278,7 +399,58 @@ class JointTest < Test::Unit::TestCase
278
399
  assert_nil subject.image_type
279
400
  assert_nil subject.image_size
280
401
  end
402
+ end
403
+
404
+ context "Setting attachment to nil on embedded document" do
405
+ setup do
406
+ @asset = Asset.new
407
+ @doc = @asset.embedded_assets.build(:image => @image)
408
+ @asset.save!
409
+ rewind_files
410
+ end
411
+ subject { @doc }
412
+
413
+ should "delete attachment after save" do
414
+ assert_no_grid_difference { subject.image = nil }
415
+ assert_grid_difference(-1) { subject.save }
416
+ end
281
417
 
418
+ should "know that the attachment has been nullified" do
419
+ subject.image = nil
420
+ subject.image?.should be(false)
421
+ end
422
+
423
+ should "respond with true when asked if the attachment is nil?" do
424
+ subject.image = nil
425
+ subject.image.nil?.should be(true)
426
+ end
427
+
428
+ should "respond with true when asked if the attachment is blank?" do
429
+ subject.image = nil
430
+ subject.image.blank?.should be(true)
431
+ end
432
+
433
+ should "clear nil attachments after save and not attempt to delete again" do
434
+ Mongo::Grid.any_instance.expects(:delete).once
435
+ subject.image = nil
436
+ subject.save
437
+ Mongo::Grid.any_instance.expects(:delete).never
438
+ subject.save
439
+ end
440
+
441
+ should "clear id, name, type, size" do
442
+ subject.image = nil
443
+ subject.save
444
+ assert_nil subject.image_id
445
+ assert_nil subject.image_name
446
+ assert_nil subject.image_type
447
+ assert_nil subject.image_size
448
+ s = subject._root_document.reload.embedded_assets.first
449
+ assert_nil s.image_id
450
+ assert_nil s.image_name
451
+ assert_nil s.image_type
452
+ assert_nil s.image_size
453
+ end
282
454
  end
283
455
 
284
456
  context "Retrieving attachment that does not exist" do
@@ -313,6 +485,22 @@ class JointTest < Test::Unit::TestCase
313
485
  end
314
486
  end
315
487
 
488
+ context "Destroying an embedded document's _root_document" do
489
+ setup do
490
+ @asset = Asset.new
491
+ @doc = @asset.embedded_assets.build(:image => @image)
492
+ @doc.save!
493
+ rewind_files
494
+ end
495
+ subject { @doc }
496
+
497
+ should "remove files from grid fs as well" do
498
+ assert_grid_difference(-1) { subject._root_document.destroy }
499
+ end
500
+ end
501
+
502
+ # What about when an embedded document is removed?
503
+
316
504
  context "Assigning file name" do
317
505
  should "default to path" do
318
506
  Asset.create(:image => @image).image.name.should == 'mr_t.jpg'
@@ -358,15 +546,14 @@ class JointTest < Test::Unit::TestCase
358
546
  io = Joint::IO.new({
359
547
  :name => 'foo.txt',
360
548
  :type => 'plain/text',
361
- :content => 'This is my stuff',
362
- :size => 19,
549
+ :content => 'This is my stuff'
363
550
  })
364
551
  @asset = Asset.create(:file => io)
365
552
  end
366
553
 
367
554
  should "work" do
368
555
  @asset.file_name.should == 'foo.txt'
369
- @asset.file_size.should == 19
556
+ @asset.file_size.should == 16
370
557
  @asset.file_type.should == 'plain/text'
371
558
  @asset.file.read.should == 'This is my stuff'
372
559
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: joint
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 6
9
- - 0
10
- version: 0.6.0
9
+ - 1
10
+ version: 0.6.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - John Nunemaker
@@ -15,12 +15,14 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-09-14 00:00:00 Z
18
+ date: 2011-12-14 00:00:00 -05:00
19
+ default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
22
+ type: :runtime
21
23
  name: wand
22
24
  prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
24
26
  none: false
25
27
  requirements:
26
28
  - - ~>
@@ -30,12 +32,12 @@ dependencies:
30
32
  - 0
31
33
  - 4
32
34
  version: "0.4"
33
- type: :runtime
34
- version_requirements: *id001
35
+ requirement: *id001
35
36
  - !ruby/object:Gem::Dependency
37
+ type: :runtime
36
38
  name: mime-types
37
39
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
40
+ version_requirements: &id002 !ruby/object:Gem::Requirement
39
41
  none: false
40
42
  requirements:
41
43
  - - ">="
@@ -44,24 +46,22 @@ dependencies:
44
46
  segments:
45
47
  - 0
46
48
  version: "0"
47
- type: :runtime
48
- version_requirements: *id002
49
+ requirement: *id002
49
50
  - !ruby/object:Gem::Dependency
51
+ type: :runtime
50
52
  name: mongo_mapper
51
53
  prerelease: false
52
- requirement: &id003 !ruby/object:Gem::Requirement
54
+ version_requirements: &id003 !ruby/object:Gem::Requirement
53
55
  none: false
54
56
  requirements:
55
57
  - - ~>
56
58
  - !ruby/object:Gem::Version
57
- hash: 59
59
+ hash: 25
58
60
  segments:
59
61
  - 0
60
62
  - 9
61
- - 0
62
- version: 0.9.0
63
- type: :runtime
64
- version_requirements: *id003
63
+ version: "0.9"
64
+ requirement: *id003
65
65
  description: MongoMapper and GridFS joined in file upload love.
66
66
  email: nunemaker@gmail.com
67
67
  executables: []
@@ -73,7 +73,6 @@ extra_rdoc_files: []
73
73
  files:
74
74
  - .gitignore
75
75
  - Gemfile
76
- - Gemfile.lock
77
76
  - LICENSE
78
77
  - README.rdoc
79
78
  - Rakefile
@@ -95,6 +94,7 @@ files:
95
94
  - test/helper.rb
96
95
  - test/joint/test_io.rb
97
96
  - test/test_joint.rb
97
+ has_rdoc: true
98
98
  homepage: http://github.com/jnunemaker/joint
99
99
  licenses: []
100
100
 
@@ -124,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
124
  requirements: []
125
125
 
126
126
  rubyforge_project:
127
- rubygems_version: 1.8.9
127
+ rubygems_version: 1.6.1
128
128
  signing_key:
129
129
  specification_version: 3
130
130
  summary: MongoMapper and GridFS joined in file upload love.
@@ -1,52 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- joint (0.6.0)
5
- mime-types
6
- mongo_mapper (~> 0.9.0)
7
- wand (~> 0.4)
8
-
9
- GEM
10
- remote: http://rubygems.org/
11
- specs:
12
- activemodel (3.1.0)
13
- activesupport (= 3.1.0)
14
- bcrypt-ruby (~> 3.0.0)
15
- builder (~> 3.0.0)
16
- i18n (~> 0.6)
17
- activesupport (3.1.0)
18
- multi_json (~> 1.0)
19
- bcrypt-ruby (3.0.1)
20
- bson (1.3.1)
21
- bson_ext (1.3.1)
22
- builder (3.0.0)
23
- i18n (0.6.0)
24
- jnunemaker-matchy (0.4.0)
25
- mime-types (1.16)
26
- mocha (0.9.10)
27
- rake
28
- mongo (1.3.1)
29
- bson (>= 1.3.1)
30
- mongo_mapper (0.9.2)
31
- activemodel (~> 3.0)
32
- activesupport (~> 3.0)
33
- plucky (~> 0.3.8)
34
- multi_json (1.0.2)
35
- plucky (0.3.8)
36
- mongo (~> 1.3)
37
- rake (0.8.7)
38
- safe_shell (1.0.0)
39
- shoulda (2.11.3)
40
- wand (0.4)
41
- mime-types
42
- safe_shell (~> 1.0.0)
43
-
44
- PLATFORMS
45
- ruby
46
-
47
- DEPENDENCIES
48
- bson_ext
49
- jnunemaker-matchy
50
- joint!
51
- mocha
52
- shoulda