versions 0.1.0 → 0.2.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.
@@ -1,3 +1,3 @@
1
1
  module Versions
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -31,7 +31,8 @@ begin
31
31
  t.string 'properties'
32
32
  t.integer 'attachment_id'
33
33
  t.integer 'number'
34
- t.integer 'owner_id'
34
+ t.integer 'page_id'
35
+ t.integer 'node_id'
35
36
  t.timestamps
36
37
  end
37
38
 
@@ -44,7 +45,10 @@ begin
44
45
  end
45
46
 
46
47
  ActiveRecord::Base.establish_connection(:adapter=>'sqlite3', :database=>':memory:')
47
- ActiveRecord::Migration.verbose = false
48
- VersionsMigration.migrate(:up)
49
- ActiveRecord::Migration.verbose = true
48
+ ActiveRecord::Base.logger = Logger.new(File.open(Pathname(__FILE__).dirname + 'test.log', 'wb'))
49
+ #if !ActiveRecord::Base.connection.table_exists?('pages')
50
+ ActiveRecord::Migration.verbose = false
51
+ VersionsMigration.migrate(:up)
52
+ ActiveRecord::Migration.verbose = true
53
+ #end
50
54
  end
@@ -1,16 +1,48 @@
1
1
  require 'rubygems'
2
2
  require 'test/unit'
3
3
  require 'shoulda'
4
+ require 'active_record'
5
+ require 'active_support'
6
+ require 'active_support/testing/assertions'
7
+ require 'tempfile'
4
8
 
5
9
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
10
  $LOAD_PATH.unshift(File.dirname(__FILE__))
7
11
 
8
- require 'active_record'
9
- require 'active_support'
10
- require 'active_support/testing/assertions'
11
12
  require 'versions'
12
13
  require 'fixtures'
13
14
 
14
15
  class Test::Unit::TestCase
15
16
  include ActiveSupport::Testing::Assertions
17
+ FILE_FIXTURES_PATH = Pathname(__FILE__).dirname + 'fixtures/files'
18
+
19
+ # taken from http://manuals.rubyonrails.com/read/chapter/28#page237 with some modifications
20
+ def uploaded_fixture(fname, content_type="application/octet-stream", filename=nil)
21
+ path = File.join(FILE_FIXTURES_PATH, fname)
22
+ filename ||= File.basename(path)
23
+ # simulate small files with StringIO
24
+ if File.stat(path).size < 1024
25
+ # smaller then 1 Ko
26
+ t = StringIO.new(File.read(path))
27
+ else
28
+ t = Tempfile.new(fname)
29
+ FileUtils.copy_file(path, t.path)
30
+ end
31
+ uploaded_file(t, filename, content_type)
32
+ end
33
+
34
+ # JPEG helper
35
+ def uploaded_jpg(fname, filename=nil)
36
+ uploaded_fixture(fname, 'image/jpeg', filename)
37
+ end
38
+
39
+ private
40
+ def uploaded_file(file, filename = nil, content_type = nil)
41
+ (class << file; self; end;).class_eval do
42
+ alias local_path path if respond_to?(:path) # FIXME: do we need this ?
43
+ define_method(:original_filename) { filename }
44
+ define_method(:content_type) { content_type }
45
+ end
46
+ file
47
+ end
16
48
  end
@@ -0,0 +1,107 @@
1
+ require 'helper'
2
+
3
+ class AfterCommitTest < Test::Unit::TestCase
4
+ class Page < ActiveRecord::Base
5
+ attr_accessor :actions
6
+ before_save :do_action
7
+ after_save :raise_to_rollback
8
+ validates_presence_of :name
9
+
10
+ def after_commit_actions
11
+ @after_commit_actions ||= []
12
+ end
13
+
14
+ private
15
+ def do_action
16
+ after_commit do
17
+ after_commit_actions << 'executed'
18
+ end
19
+ end
20
+
21
+ def raise_to_rollback
22
+ raise ActiveRecord::Rollback if self[:name] == 'raise'
23
+ end
24
+ end
25
+
26
+ context 'Creating a valid page' do
27
+ should 'trigger after_commit once all is done' do
28
+ page = Page.create(:name => 'hello')
29
+ assert_equal ['executed'], page.after_commit_actions
30
+ end
31
+
32
+ context 'inside a transaction' do
33
+ should 'trigger after_commit after last transaction' do
34
+ page = nil
35
+ Page.transaction do
36
+ page = Page.create(:name => 'hello')
37
+ assert_equal [], page.after_commit_actions
38
+ end
39
+ assert_equal ['executed'], page.after_commit_actions
40
+ end
41
+
42
+ should 'not trigger after_commit if outer transaction fails' do
43
+ page = nil
44
+ begin
45
+ Page.transaction do
46
+ page = Page.create(:name => 'hello')
47
+ assert_equal [], page.after_commit_actions
48
+ raise 'Something went bad'
49
+ end
50
+ rescue Exception => err
51
+ end
52
+ assert_equal [], page.after_commit_actions
53
+ end
54
+
55
+ should 'not trigger after_commit on rollback' do
56
+ page = nil
57
+ Page.transaction do
58
+ page = Page.create(:name => 'hello')
59
+ assert_equal [], page.after_commit_actions
60
+ raise ActiveRecord::Rollback
61
+ end
62
+ assert_equal [], page.after_commit_actions
63
+ end
64
+
65
+ should 'clear after_commit after transaction' do
66
+ actions = []
67
+ Page.transaction do
68
+ Page.after_commit do
69
+ actions << 'executed'
70
+ end
71
+ raise ActiveRecord::Rollback
72
+ end
73
+ assert_equal [], actions
74
+
75
+ Page.transaction do
76
+ end
77
+ assert_equal [], actions
78
+ end
79
+
80
+ end
81
+ end
82
+
83
+ context 'Creating an invalid page' do
84
+ should 'not trigger after_commit' do
85
+ page = Page.create
86
+ assert page.new_record?
87
+ assert_equal [], page.after_commit_actions
88
+ end
89
+ end
90
+
91
+ context 'Raising an error after save' do
92
+ should 'not trigger after_commit' do
93
+ page = Page.create(:name => 'raise')
94
+ assert_equal [], page.after_commit_actions
95
+ end
96
+ end
97
+
98
+ should 'not allow after commit outside of a transaction' do
99
+ assert_raise(Exception) do
100
+ Page.new.instance_eval do
101
+ after_commit do
102
+ # never executed
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -1,222 +1,260 @@
1
1
  require 'helper'
2
2
 
3
- #class SharedAttachmentTest < Zena::Unit::TestCase
4
- # self.use_transactional_fixtures = false
5
- #
6
- # Attachment = Class.new(Zena::Use::SharedAttachment::Attachment) do
7
- # def filepath
8
- # File.join(RAILS_ROOT, 'tmp', 'attachments', super)
9
- # end
10
- # end
11
- #
12
- # # Mock a document class with many versions
13
- # class Document < ActiveRecord::Base
14
- # include Zena::Use::MultiVersion
15
- #
16
- # set_table_name :nodes
17
- # before_save :set_dummy_defaults
18
- #
19
- # def title=(title)
20
- # version.title = title
21
- # end
22
- #
23
- # def file=(file)
24
- # version.file = file
25
- # end
26
- #
27
- # def version
28
- # @version ||= new_record? ? versions.build : versions.first(:order => 'id DESC')
29
- # end
30
- # private
31
- # def set_dummy_defaults
32
- # self[:user_id] ||= 0
33
- # end
34
- # end
35
- #
36
- # # Mock a version class with shared attachments (between versions of the same document)
37
- # class Version < ActiveRecord::Base
38
- # include Zena::Use::MultiVersion::Version
39
- # include Zena::Use::AutoVersion
40
- # include Zena::Use::SharedAttachment
41
- # set_attachment_class 'SharedAttachmentTest::Attachment'
42
- # set_table_name :versions
43
- #
44
- # def should_clone?
45
- # true
46
- # end
47
- #
48
- # private
49
- # def setup_version_on_create
50
- # # Dummy values when testing Version without a Document
51
- # self[:node_id] ||= 0
52
- # self[:user_id] ||= 0
53
- # self[:status] ||= 0
54
- # end
55
- # end
56
- #
57
- # def setup
58
- # FileUtils.rmtree(File.join(RAILS_ROOT, 'tmp', 'attachments'))
59
- # end
60
- #
61
- # context 'When creating a new owner' do
62
- # setup do
63
- # @owner = Version.create(:file => uploaded_jpg('bird.jpg'))
64
- # end
65
- #
66
- # should 'store file in the filesystem' do
67
- # assert File.exist?(@owner.filepath)
68
- # assert_equal uploaded_jpg('bird.jpg').read, File.read(@owner.filepath)
69
- # end
70
- #
71
- # should 'restore the filepath from the database' do
72
- # attachment = Attachment.find(@owner.attachment_id)
73
- # assert_equal @owner.filepath, attachment.filepath
74
- # end
75
- # end
76
- #
77
- # context 'When the transaction fails' do
78
- # should 'not write file on create' do
79
- # owner = nil
80
- # filepath = nil
81
- # assert_difference('Attachment.count', 0) do
82
- # Version.transaction do
83
- # owner = Version.create(:file => uploaded_jpg('bird.jpg'))
84
- # filepath = owner.filepath
85
- # assert !File.exist?(filepath)
86
- # raise ActiveRecord::Rollback
87
- # end
88
- # end
89
- # assert !File.exist?(filepath)
90
- # end
91
- #
92
- # should 'not remove file on destroy' do
93
- # @owner = Version.create(:file => uploaded_jpg('bird.jpg'))
94
- # filepath = @owner.filepath
95
- # assert File.exist?(filepath)
96
- # assert_difference('Attachment.count', 0) do
97
- # Version.transaction do
98
- # @owner.destroy
99
- # assert File.exist?(filepath)
100
- # raise ActiveRecord::Rollback
101
- # end
102
- # end
103
- # assert File.exist?(filepath)
104
- # end
105
- # end
106
- #
107
- # context 'On an owner with a file' do
108
- # setup do
109
- # @owner = Version.create(:file => uploaded_jpg('bird.jpg'))
110
- # @owner = Version.find(@owner.id)
111
- # end
112
- #
113
- # should 'remove file in the filesystem when updating file' do
114
- # old_filepath = @owner.filepath
115
- # puts "Start"
116
- # assert_difference('Attachment.count', 0) do # destroy + create
117
- # assert @owner.update_attributes(:file => uploaded_jpg('lake.jpg'))
118
- # end
119
- # assert_not_equal old_filepath, @owner.filepath
120
- # assert File.exist?(@owner.filepath)
121
- # assert_equal uploaded_jpg('lake.jpg').read, File.read(@owner.filepath)
122
- # assert !File.exist?(old_filepath)
123
- # end
124
- # end
125
- #
126
- # context 'Updating document' do
127
- # setup do
128
- # begin
129
- # @doc = Document.create(:title => 'birdy', :file => uploaded_jpg('bird.jpg'))
130
- # rescue => err
131
- # puts err.message
132
- # puts err.backtrace.join("\n")
133
- # end
134
- # end
135
- #
136
- # # Updating document ...attributes
137
- # context 'attributes' do
138
- # setup do
139
- # assert_difference('Version.count', 1) do
140
- # @doc.update_attributes(:title => 'hopla')
141
- # end
142
- # end
143
- #
144
- # should 'reuse the same filepath in new versions' do
145
- # filepath = nil
146
- # @doc.versions.each do |version|
147
- # if filepath
148
- # assert_equal filepath, version.filepath
149
- # else
150
- # filepath = version.filepath
151
- # end
152
- # end
153
- # end
154
- # end
155
- #
156
- # # Updating document ...file
157
- # context 'file' do
158
- # setup do
159
- # assert_difference('Version.count', 1) do
160
- # @doc.update_attributes(:file => uploaded_jpg('lake.jpg'))
161
- # end
162
- # end
163
- #
164
- # should 'create new filepath' do
165
- # filepath = nil
166
- # @doc.versions.each do |version|
167
- # if filepath
168
- # assert_not_equal filepath, version.filepath
169
- # else
170
- # filepath = version.filepath
171
- # end
172
- # end
173
- # end
174
- # end # Updating document .. file
175
- # end # Updating document
176
- #
177
- # context 'On a document with many versions' do
178
- # setup do
179
- # assert_difference('Version.count', 2) do
180
- # @doc = Document.create(:title => 'birdy', :file => uploaded_jpg('bird.jpg'))
181
- # @doc.update_attributes(:title => 'Vögel')
182
- # @doc = Document.find(@doc.id)
183
- # end
184
- # end
185
- #
186
- # context 'removing a version' do
187
- #
188
- # should 'not remove shared attachment' do
189
- # filepath = @doc.version.filepath
190
- #
191
- # assert_difference('Version.count', -1) do
192
- # assert_difference('Attachment.count', 0) do
193
- # assert @doc.version.destroy
194
- # end
195
- # end
196
- # assert File.exist?(filepath)
197
- # end
198
- # end
199
- #
200
- # context 'removing the last version' do
201
- #
202
- # should 'remove shared attachment' do
203
- # filepath = @doc.version.filepath
204
- #
205
- # assert_difference('Version.count', -2) do
206
- # assert_difference('Attachment.count', -1) do
207
- # @doc.versions.each do |version|
208
- # assert version.destroy
209
- # end
210
- # end
211
- # end
212
- # assert !File.exist?(filepath)
213
- # end
214
- # end
215
- # end
216
- #
217
- # private
218
- # def filepath(attachment_id, filename)
219
- # digest = Digest::SHA1.hexdigest(attachment_id.to_s)
220
- # "#{digest[0..0]}/#{digest[1..1]}/#{filename}"
221
- # end
222
- #end
3
+ class AttachmentTest < Test::Unit::TestCase
4
+ @@attachments_dir = (Pathname(__FILE__).dirname + 'tmp').expand_path
5
+
6
+ Attachment = Class.new(Versions::SharedAttachment) do
7
+ def filepath
8
+ File.join(@@attachments_dir, super)
9
+ end
10
+ end
11
+
12
+ # Mock a version class with shared attachments (between versions of the same document)
13
+ class Version < ActiveRecord::Base
14
+ include Versions::Auto
15
+ end
16
+
17
+ # Mock a document class with many versions
18
+ class Document < ActiveRecord::Base
19
+ include Versions::Multi
20
+ has_multiple :versions, :class_name => 'AttachmentTest::Version', :inverse => 'node'
21
+
22
+ include Versions::Attachment
23
+ store_attachments_in :version, :class_name => 'AttachmentTest::Version', :attachment_class => 'AttachmentTest::Attachment'
24
+
25
+ set_table_name :pages
26
+
27
+ def title
28
+ version.title
29
+ end
30
+
31
+ def title=(t)
32
+ version.title = t
33
+ end
34
+ end
35
+
36
+
37
+ def setup
38
+ FileUtils.rmtree(@@attachments_dir)
39
+ end
40
+
41
+ context 'When creating a new owner' do
42
+ setup do
43
+ @owner = Version.create(:file => uploaded_jpg('bird.jpg'))
44
+ end
45
+
46
+ should 'store file in the filesystem' do
47
+ assert File.exist?(@owner.filepath)
48
+ assert_equal uploaded_jpg('bird.jpg').read, File.read(@owner.filepath)
49
+ end
50
+
51
+ should 'restore the filepath from the database' do
52
+ attachment = Attachment.find(@owner.attachment_id)
53
+ assert_equal @owner.filepath, attachment.filepath
54
+ end
55
+
56
+ should 'rename file on bad original_filename' do
57
+ file = uploaded_jpg('bird.jpg')
58
+ class << file
59
+ def original_filename
60
+ '../../bad.txt'
61
+ end
62
+ end
63
+ owner = Version.create(:file => file)
64
+ assert File.exist?(owner.filepath)
65
+ assert_no_match %r{bird\.jpg}, owner.filepath
66
+ assert_no_match %r{bad\.txt}, owner.filepath
67
+ end
68
+ end
69
+
70
+ context 'When the transaction fails' do
71
+ should 'not write file on create' do
72
+ owner = nil
73
+ filepath = nil
74
+ assert_difference('Attachment.count', 0) do
75
+ Version.transaction do
76
+ owner = Version.create(:file => uploaded_jpg('bird.jpg'))
77
+ filepath = owner.filepath
78
+ assert !File.exist?(filepath)
79
+ raise ActiveRecord::Rollback
80
+ end
81
+ end
82
+ assert !File.exist?(filepath)
83
+ end
84
+
85
+ should 'not remove file on destroy' do
86
+ @owner = Version.create(:file => uploaded_jpg('bird.jpg'))
87
+ filepath = @owner.filepath
88
+ assert File.exist?(filepath)
89
+ assert_difference('Attachment.count', 0) do
90
+ Version.transaction do
91
+ @owner.destroy
92
+ assert File.exist?(filepath)
93
+ raise ActiveRecord::Rollback
94
+ end
95
+ end
96
+ assert File.exist?(filepath)
97
+ end
98
+ end
99
+
100
+ context 'On an owner with a file' do
101
+ setup do
102
+ @owner = Version.create(:file => uploaded_jpg('bird.jpg'))
103
+ @owner = Version.find(@owner.id)
104
+ @owner.class_eval do
105
+ def should_clone?
106
+ false
107
+ end
108
+ end
109
+ end
110
+
111
+ should 'remove file in the filesystem when updating file' do
112
+ old_filepath = @owner.filepath
113
+ assert_difference('Attachment.count', 0) do # destroy + create
114
+ assert @owner.update_attributes(:file => uploaded_jpg('lake.jpg'))
115
+ end
116
+ assert_not_equal old_filepath, @owner.filepath
117
+ assert File.exist?(@owner.filepath)
118
+ assert_equal uploaded_jpg('lake.jpg').read, File.read(@owner.filepath)
119
+ assert !File.exist?(old_filepath)
120
+ end
121
+ end
122
+
123
+ context 'Updating document' do
124
+ setup do
125
+ begin
126
+ @doc = Document.create(:title => 'birdy', :file => uploaded_jpg('bird.jpg'))
127
+ rescue => err
128
+ puts err.message
129
+ puts err.backtrace.join("\n")
130
+ end
131
+ end
132
+
133
+ # Updating document ...attributes
134
+ context 'attributes' do
135
+ setup do
136
+ assert_difference('Version.count', 1) do
137
+ @doc.update_attributes(:title => 'hopla')
138
+ end
139
+ end
140
+
141
+ should 'reuse the same filepath in new versions' do
142
+ filepath = nil
143
+ @doc.versions.each do |version|
144
+ if filepath
145
+ assert_equal filepath, version.filepath
146
+ else
147
+ filepath = version.filepath
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ # Updating document ...file
154
+ context 'file' do
155
+ setup do
156
+ assert_difference('Version.count', 1) do
157
+ @doc.update_attributes(:file => uploaded_jpg('lake.jpg'))
158
+ end
159
+ end
160
+
161
+ should 'create new filepath' do
162
+ filepath = nil
163
+ @doc.versions.each do |version|
164
+ if filepath
165
+ assert_not_equal filepath, version.filepath
166
+ else
167
+ filepath = version.filepath
168
+ end
169
+ end
170
+ end
171
+ end # Updating document .. file
172
+ end # Updating document
173
+
174
+ context 'On a document with many versions' do
175
+ setup do
176
+ assert_difference('Version.count', 2) do
177
+ @doc = Document.create(:title => 'birdy', :file => uploaded_jpg('bird.jpg'))
178
+ @doc.update_attributes(:title => 'Vögel')
179
+ @doc = Document.find(@doc.id)
180
+ end
181
+ end
182
+
183
+ context 'removing a version' do
184
+
185
+ should 'not remove shared attachment' do
186
+ filepath = @doc.version.filepath
187
+
188
+ assert_difference('Version.count', -1) do
189
+ assert_difference('Attachment.count', 0) do
190
+ assert @doc.version.destroy
191
+ end
192
+ end
193
+ assert File.exist?(filepath)
194
+ end
195
+ end
196
+
197
+ context 'removing the last version' do
198
+
199
+ should 'remove shared attachment' do
200
+ filepath = @doc.version.filepath
201
+
202
+ assert_difference('Version.count', -2) do
203
+ assert_difference('Attachment.count', -1) do
204
+ @doc.versions.each do |version|
205
+ assert version.destroy
206
+ end
207
+ end
208
+ end
209
+ assert !File.exist?(filepath)
210
+ end
211
+ end
212
+ end
213
+
214
+ context 'A module using attachments without versions' do
215
+ class Doc < ActiveRecord::Base
216
+ set_table_name :versions
217
+ include Versions::Attachment
218
+ store_attachments_in self, :attachment_class => 'AttachmentTest::Attachment'
219
+ end
220
+
221
+ subject do
222
+ Doc.create('file' => uploaded_jpg('bird.jpg'))
223
+ end
224
+
225
+ should 'accept files' do
226
+ assert !subject.new_record?
227
+ end
228
+
229
+ should 'store file in the filesystem' do
230
+ assert File.exist?(subject.filepath)
231
+ assert_equal uploaded_jpg('bird.jpg').read, File.read(subject.filepath)
232
+ end
233
+
234
+ should 'restore the filepath from the database' do
235
+ attachment = Attachment.find(subject.attachment_id)
236
+ assert_equal subject.filepath, attachment.filepath
237
+ end
238
+
239
+ should 'remove file in the filesystem when updating file' do
240
+ old_filepath = subject.filepath
241
+ assert_difference('Attachment.count', 0) do # destroy + create
242
+ assert subject.update_attributes(:file => uploaded_jpg('lake.jpg'))
243
+ end
244
+ assert_not_equal old_filepath, subject.filepath
245
+ assert File.exist?(subject.filepath)
246
+ assert_equal uploaded_jpg('lake.jpg').read, File.read(subject.filepath)
247
+ assert !File.exist?(old_filepath)
248
+ end
249
+
250
+ should 'create and destroy objects without attachments' do
251
+ assert Doc.create.destroy
252
+ end
253
+ end
254
+
255
+ private
256
+ def filepath(attachment_id, filename)
257
+ digest = Digest::SHA1.hexdigest(attachment_id.to_s)
258
+ "#{digest[0..0]}/#{digest[1..1]}/#{filename}"
259
+ end
260
+ end