joint 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
- require 'yard'
4
3
  require 'jeweler'
5
4
  require 'rake/testtask'
6
5
 
@@ -21,7 +20,10 @@ Jeweler::Tasks.new do |gem|
21
20
  gem.add_dependency 'mime-types'
22
21
 
23
22
  gem.add_development_dependency 'jeweler'
24
- gem.add_development_dependency 'mongo_mapper'
23
+ gem.add_development_dependency 'shoulda'
24
+ gem.add_development_dependency 'mocha'
25
+ gem.add_development_dependency 'jnunemaker-matchy'
26
+ gem.add_development_dependency 'mongo_mapper', '>= 0.7.2'
25
27
  end
26
28
  Jeweler::GemcutterTasks.new
27
29
 
@@ -8,7 +8,7 @@ module Joint
8
8
  module ClassMethods
9
9
  def attachment(name)
10
10
  self.class.class_inheritable_accessor :attachment_names unless self.class.respond_to?(:attachment_names)
11
- self.class.attachment_names ||= []
11
+ self.class.attachment_names ||= Set.new
12
12
  self.class.attachment_names << name
13
13
 
14
14
  after_save :save_attachments
@@ -33,10 +33,10 @@ module Joint
33
33
  if file.nil?
34
34
  nil_attachments << :#{name}
35
35
  else
36
- self["#{name}_id"] = Mongo::ObjectID.new
37
- self["#{name}_size"] = File.size(file)
38
- self["#{name}_type"] = Wand.wave(file.path)
39
- self["#{name}_name"] = Joint.file_name(file)
36
+ self["#{name}_id"] = Mongo::ObjectID.new if self["#{name}_id"].nil?
37
+ self["#{name}_size"] = File.size(file)
38
+ self["#{name}_type"] = Wand.wave(file.path)
39
+ self["#{name}_name"] = Joint.file_name(file)
40
40
  assigned_attachments[:#{name}] = file
41
41
  end
42
42
  end
@@ -58,25 +58,27 @@ module Joint
58
58
  @nil_attachments ||= Set.new
59
59
  end
60
60
 
61
+ # IO must respond to read and rewind
61
62
  def save_attachments
62
- assigned_attachments.each do |attachment|
63
- name, file = attachment
64
- if file.respond_to?(:read)
65
- file.rewind if file.respond_to?(:rewind)
66
- grid.put(file.read, self["#{name}_name"], {
67
- :_id => self["#{name}_id"],
68
- :content_type => self["#{name}_type"],
69
- })
70
- end
71
- end.tap(&:clear)
63
+ assigned_attachments.each_pair do |name, io|
64
+ next unless io.respond_to?(:read)
65
+ io.rewind if io.respond_to?(:rewind)
66
+ grid.delete(send(name).id)
67
+ grid.put(io.read, send(name).name, {
68
+ :_id => send(name).id,
69
+ :content_type => send(name).type,
70
+ })
71
+ end
72
+ assigned_attachments.clear
72
73
  end
73
74
 
74
75
  def destroy_nil_attachments
75
- nil_attachments.each { |name| grid.delete(self["#{name}_id"]) }.tap(&:clear)
76
+ nil_attachments.each { |name| grid.delete(send(name).id) }
77
+ nil_attachments.clear
76
78
  end
77
79
 
78
80
  def destroy_all_attachments
79
- self.class.attachment_names.each { |name| grid.delete(self["#{name}_id"]) }
81
+ self.class.attachment_names.map { |name| grid.delete(send(name).id) }
80
82
  end
81
83
  end
82
84
 
@@ -1,3 +1,3 @@
1
1
  module Joint
2
- Version = '0.2'
2
+ Version = '0.3'
3
3
  end
Binary file
@@ -0,0 +1 @@
1
+ test1
@@ -0,0 +1 @@
1
+ test2
@@ -1,15 +1,19 @@
1
1
  require 'tempfile'
2
2
  require 'pp'
3
- require 'mongo_mapper'
4
3
  require 'shoulda'
5
4
  require 'matchy'
6
5
  require 'mocha'
6
+ require 'mongo_mapper'
7
7
 
8
8
  require File.expand_path(File.dirname(__FILE__) + '/../lib/joint')
9
9
 
10
10
  MongoMapper.database = "testing"
11
11
 
12
12
  class Test::Unit::TestCase
13
+ def setup
14
+ MongoMapper.database.collections.each(&:remove)
15
+ end
16
+
13
17
  def assert_difference(expression, difference = 1, message = nil, &block)
14
18
  b = block.send(:binding)
15
19
  exps = Array.wrap(expression)
@@ -25,4 +29,12 @@ class Test::Unit::TestCase
25
29
  def assert_no_difference(expression, message = nil, &block)
26
30
  assert_difference(expression, 0, message, &block)
27
31
  end
32
+
33
+ def assert_grid_difference(difference=1, &block)
34
+ assert_difference("MongoMapper.database['fs.files'].find().count", difference, &block)
35
+ end
36
+
37
+ def assert_no_grid_difference(&block)
38
+ assert_grid_difference(0, &block)
39
+ end
28
40
  end
@@ -6,105 +6,151 @@ class Asset
6
6
 
7
7
  key :title, String
8
8
  attachment :image
9
- attachment :pdf
9
+ attachment :file
10
+ end
11
+
12
+ module JointTestHelpers
13
+ def all_files
14
+ [@file, @image, @image2, @test1, @test2]
15
+ end
16
+
17
+ def rewind_files
18
+ all_files.each { |file| file.rewind }
19
+ end
20
+
21
+ def open_file(name)
22
+ File.open(File.join(File.dirname(__FILE__), 'fixtures', name), 'r')
23
+ end
24
+
25
+ def grid
26
+ @grid ||= Mongo::Grid.new(MongoMapper.database)
27
+ end
10
28
  end
11
29
 
12
30
  class JointTest < Test::Unit::TestCase
31
+ include JointTestHelpers
32
+
13
33
  def setup
14
- MongoMapper.database.collections.each(&:remove)
15
-
16
- dir = File.dirname(__FILE__) + '/fixtures'
17
- @pdf = File.open("#{dir}/unixref.pdf", 'r')
18
- @image = File.open("#{dir}/mr_t.jpg", 'r')
19
- @pdf_contents = File.read("#{dir}/unixref.pdf")
20
- @image_contents = File.read("#{dir}/mr_t.jpg")
21
- @grid = Mongo::Grid.new(MongoMapper.database)
22
- @gridfs_collection = MongoMapper.database['fs.files']
34
+ super
35
+ @file = open_file('unixref.pdf')
36
+ @image = open_file('mr_t.jpg')
37
+ @image2 = open_file('harmony.png')
38
+ @test1 = open_file('test1.txt')
39
+ @test2 = open_file('test2.txt')
23
40
  end
24
41
 
25
42
  def teardown
26
- @pdf.close
27
- @image.close
43
+ all_files.each { |file| file.close }
28
44
  end
29
45
 
30
46
  context "Using Joint plugin" do
31
47
  should "add each attachment to attachment_names" do
32
- Asset.attachment_names.should == [:image, :pdf]
48
+ Asset.attachment_names.should == Set.new([:image, :file])
33
49
  end
34
50
 
35
51
  should "add keys for each attachment" do
36
- [:image, :pdf].each do |attachment|
52
+ [:image, :file].each do |attachment|
37
53
  [:id, :name, :type, :size].each do |key|
38
- Asset.keys.include?("#{attachment}_#{key}")
54
+ Asset.keys.should include("#{attachment}_#{key}")
39
55
  end
40
56
  end
41
57
  end
42
58
  end
43
59
 
44
- context "Assigning attachments to document" do
60
+ context "Assigning new attachments to document" do
45
61
  setup do
46
- @doc = Asset.create(:image => @image, :pdf => @pdf)
47
- @doc.reload
62
+ @doc = Asset.create(:image => @image, :file => @file)
63
+ rewind_files
48
64
  end
65
+ subject { @doc }
49
66
 
50
67
  should "assign GridFS content_type" do
51
- @grid.get(@doc.image_id).content_type.should == 'image/jpeg'
52
- @grid.get(@doc.pdf_id).content_type.should == 'application/pdf'
68
+ grid.get(subject.image_id).content_type.should == 'image/jpeg'
69
+ grid.get(subject.file_id).content_type.should == 'application/pdf'
53
70
  end
54
71
 
55
72
  should "assign joint keys" do
56
- @doc.image_size.should == 13661
57
- @doc.pdf_size.should == 68926
73
+ subject.image_size.should == 13661
74
+ subject.file_size.should == 68926
58
75
 
59
- @doc.image_type.should == "image/jpeg"
60
- @doc.pdf_type.should == "application/pdf"
76
+ subject.image_type.should == "image/jpeg"
77
+ subject.file_type.should == "application/pdf"
61
78
 
62
- @doc.image_id.should_not be_nil
63
- @doc.pdf_id.should_not be_nil
79
+ subject.image_id.should_not be_nil
80
+ subject.file_id.should_not be_nil
64
81
 
65
- @doc.image_id.should be_instance_of(Mongo::ObjectID)
66
- @doc.pdf_id.should be_instance_of(Mongo::ObjectID)
82
+ subject.image_id.should be_instance_of(Mongo::ObjectID)
83
+ subject.file_id.should be_instance_of(Mongo::ObjectID)
67
84
  end
68
85
 
69
86
  should "allow accessing keys through attachment proxy" do
70
- @doc.image.size.should == 13661
71
- @doc.pdf.size.should == 68926
87
+ subject.image.size.should == 13661
88
+ subject.file.size.should == 68926
72
89
 
73
- @doc.image.type.should == "image/jpeg"
74
- @doc.pdf.type.should == "application/pdf"
90
+ subject.image.type.should == "image/jpeg"
91
+ subject.file.type.should == "application/pdf"
75
92
 
76
- @doc.image.id.should_not be_nil
77
- @doc.pdf.id.should_not be_nil
93
+ subject.image.id.should_not be_nil
94
+ subject.file.id.should_not be_nil
78
95
 
79
- @doc.image.id.should be_instance_of(Mongo::ObjectID)
80
- @doc.pdf.id.should be_instance_of(Mongo::ObjectID)
96
+ subject.image.id.should be_instance_of(Mongo::ObjectID)
97
+ subject.file.id.should be_instance_of(Mongo::ObjectID)
81
98
  end
82
99
 
83
100
  should "proxy unknown methods to GridIO object" do
84
- @doc.image.files_id.should == @doc.image_id
85
- @doc.image.content_type.should == 'image/jpeg'
86
- @doc.image.filename.should == 'mr_t.jpg'
87
- @doc.image.file_length.should == 13661
101
+ subject.image.files_id.should == subject.image_id
102
+ subject.image.content_type.should == 'image/jpeg'
103
+ subject.image.filename.should == 'mr_t.jpg'
104
+ subject.image.file_length.should == 13661
88
105
  end
89
106
 
90
107
  should "assign file name from path if original file name not available" do
91
- @doc.image_name.should == 'mr_t.jpg'
92
- @doc.pdf_name.should == 'unixref.pdf'
108
+ subject.image_name.should == 'mr_t.jpg'
109
+ subject.file_name.should == 'unixref.pdf'
93
110
  end
94
111
 
95
112
  should "save attachment contents correctly" do
96
- @doc.pdf.read.should == @pdf_contents
97
- @doc.image.read.should == @image_contents
113
+ subject.file.read.should == @file.read
114
+ subject.image.read.should == @image.read
98
115
  end
99
116
 
100
117
  should "know that attachment exists" do
101
- @doc.image?.should be(true)
102
- @doc.pdf?.should be(true)
118
+ subject.image?.should be(true)
119
+ subject.file?.should be(true)
103
120
  end
104
121
 
105
122
  should "clear assigned attachments so they don't get uploaded twice" do
106
123
  Mongo::Grid.any_instance.expects(:put).never
107
- @doc.save
124
+ subject.save
125
+ end
126
+ end
127
+
128
+ context "Updating existing attachment" do
129
+ setup do
130
+ @doc = Asset.create(:file => @test1)
131
+ assert_no_grid_difference do
132
+ @doc.file = @test2
133
+ @doc.save!
134
+ end
135
+ rewind_files
136
+ end
137
+ subject { @doc }
138
+
139
+ should "not change attachment id" do
140
+ subject.file_id_changed?.should be(false)
141
+ end
142
+
143
+ should "update keys" do
144
+ subject.file_name.should == 'test2.txt'
145
+ subject.file_type.should == "text/plain"
146
+ subject.file_size.should == 5
147
+ end
148
+
149
+ should "update GridFS" do
150
+ grid.get(subject.file_id).filename.should == 'test2.txt'
151
+ grid.get(subject.file_id).content_type.should == 'text/plain'
152
+ grid.get(subject.file_id).file_length.should == 5
153
+ grid.get(subject.file_id).read.should == @test2.read
108
154
  end
109
155
  end
110
156
 
@@ -113,75 +159,79 @@ class JointTest < Test::Unit::TestCase
113
159
  @doc = Asset.create(:image => @image)
114
160
  @doc.update_attributes(:title => 'Updated')
115
161
  @doc.reload
162
+ rewind_files
116
163
  end
164
+ subject { @doc }
117
165
 
118
166
  should "not affect attachment" do
119
- @doc.image.read.should == @image_contents
167
+ subject.image.read.should == @image.read
120
168
  end
121
169
 
122
170
  should "update document attributes" do
123
- @doc.title.should == 'Updated'
171
+ subject.title.should == 'Updated'
124
172
  end
125
173
  end
126
174
 
127
- context "Assigning file with where file pointer is not at beginning" do
175
+ context "Assigning file where file pointer is not at beginning" do
128
176
  setup do
129
177
  @image.read
130
178
  @doc = Asset.create(:image => @image)
131
179
  @doc.reload
180
+ rewind_files
132
181
  end
182
+ subject { @doc }
133
183
 
134
184
  should "rewind and correctly store contents" do
135
- @doc.image.read.should == @image_contents
185
+ subject.image.read.should == @image.read
136
186
  end
137
187
  end
138
188
 
139
189
  context "Setting attachment to nil" do
140
190
  setup do
141
191
  @doc = Asset.create(:image => @image)
192
+ rewind_files
142
193
  end
194
+ subject { @doc }
143
195
 
144
196
  should "delete attachment after save" do
145
- assert_no_difference '@gridfs_collection.find().count' do
146
- @doc.image = nil
147
- end
148
-
149
- assert_difference '@gridfs_collection.find().count', -1 do
150
- @doc.save
151
- end
197
+ assert_no_grid_difference { subject.image = nil }
198
+ assert_grid_difference(-1) { subject.save }
152
199
  end
153
-
200
+
154
201
  should "clear nil attachments after save and not attempt to delete again" do
155
- @doc.image = nil
156
- @doc.save
202
+ Mongo::Grid.any_instance.expects(:delete).once
203
+ subject.image = nil
204
+ subject.save
157
205
  Mongo::Grid.any_instance.expects(:delete).never
158
- @doc.save
206
+ subject.save
159
207
  end
160
208
  end
161
209
 
162
210
  context "Retrieving attachment that does not exist" do
163
211
  setup do
164
212
  @doc = Asset.create
213
+ rewind_files
165
214
  end
215
+ subject { @doc }
166
216
 
167
217
  should "know that the attachment is not present" do
168
- @doc.image?.should be(false)
218
+ subject.image?.should be(false)
169
219
  end
170
220
 
171
221
  should "raise Mongo::GridError" do
172
- assert_raises(Mongo::GridError) { @doc.image.read }
222
+ assert_raises(Mongo::GridError) { subject.image.read }
173
223
  end
174
224
  end
175
225
 
176
226
  context "Destroying a document" do
177
227
  setup do
178
228
  @doc = Asset.create(:image => @image)
229
+ rewind_files
179
230
  end
231
+ subject { @doc }
180
232
 
181
233
  should "remove files from grid fs as well" do
182
- assert_difference "@gridfs_collection.find().count", -1 do
183
- @doc.destroy
184
- end
234
+ assert_grid_difference(-1) { subject.destroy }
185
235
  end
186
236
  end
187
237
 
@@ -191,16 +241,11 @@ class JointTest < Test::Unit::TestCase
191
241
  end
192
242
 
193
243
  should "use original_filename if available" do
194
- begin
195
- file = Tempfile.new('testing.txt')
196
- def file.original_filename
197
- 'testing.txt'
198
- end
199
- doc = Asset.create(:image => file)
200
- assert_equal 'testing.txt', doc.image_name
201
- ensure
202
- file.close
244
+ def @image.original_filename
245
+ 'testing.txt'
203
246
  end
247
+ doc = Asset.create(:image => @image)
248
+ assert_equal 'testing.txt', doc.image_name
204
249
  end
205
250
  end
206
251
  end
metadata CHANGED
@@ -4,8 +4,8 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
8
- version: "0.2"
7
+ - 3
8
+ version: "0.3"
9
9
  platform: ruby
10
10
  authors:
11
11
  - John Nunemaker
@@ -13,7 +13,7 @@ autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
15
 
16
- date: 2010-03-29 00:00:00 -04:00
16
+ date: 2010-04-05 00:00:00 -04:00
17
17
  default_executable:
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
@@ -55,7 +55,7 @@ dependencies:
55
55
  type: :development
56
56
  version_requirements: *id003
57
57
  - !ruby/object:Gem::Dependency
58
- name: mongo_mapper
58
+ name: shoulda
59
59
  prerelease: false
60
60
  requirement: &id004 !ruby/object:Gem::Requirement
61
61
  requirements:
@@ -66,6 +66,44 @@ dependencies:
66
66
  version: "0"
67
67
  type: :development
68
68
  version_requirements: *id004
69
+ - !ruby/object:Gem::Dependency
70
+ name: mocha
71
+ prerelease: false
72
+ requirement: &id005 !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ type: :development
80
+ version_requirements: *id005
81
+ - !ruby/object:Gem::Dependency
82
+ name: jnunemaker-matchy
83
+ prerelease: false
84
+ requirement: &id006 !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ type: :development
92
+ version_requirements: *id006
93
+ - !ruby/object:Gem::Dependency
94
+ name: mongo_mapper
95
+ prerelease: false
96
+ requirement: &id007 !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ segments:
101
+ - 0
102
+ - 7
103
+ - 2
104
+ version: 0.7.2
105
+ type: :development
106
+ version_requirements: *id007
69
107
  description: MongoMapper and GridFS joined in file upload love.
70
108
  email: nunemaker@gmail.com
71
109
  executables: []
@@ -79,7 +117,10 @@ files:
79
117
  - Rakefile
80
118
  - lib/joint.rb
81
119
  - lib/joint/version.rb
120
+ - test/fixtures/harmony.png
82
121
  - test/fixtures/mr_t.jpg
122
+ - test/fixtures/test1.txt
123
+ - test/fixtures/test2.txt
83
124
  - test/fixtures/unixref.pdf
84
125
  - test/helper.rb
85
126
  - test/test_joint.rb
@@ -114,7 +155,10 @@ signing_key:
114
155
  specification_version: 3
115
156
  summary: MongoMapper and GridFS joined in file upload love.
116
157
  test_files:
158
+ - test/fixtures/harmony.png
117
159
  - test/fixtures/mr_t.jpg
160
+ - test/fixtures/test1.txt
161
+ - test/fixtures/test2.txt
118
162
  - test/fixtures/unixref.pdf
119
163
  - test/helper.rb
120
164
  - test/test_joint.rb