leifcr-refile 0.6.3
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/app/assets/javascripts/refile.js +125 -0
- data/config/locales/en.yml +10 -0
- data/config/routes.rb +5 -0
- data/lib/refile.rb +510 -0
- data/lib/refile/app.rb +186 -0
- data/lib/refile/attacher.rb +190 -0
- data/lib/refile/attachment.rb +108 -0
- data/lib/refile/attachment/active_record.rb +133 -0
- data/lib/refile/attachment_definition.rb +83 -0
- data/lib/refile/backend/file_system.rb +120 -0
- data/lib/refile/backend/s3.rb +1 -0
- data/lib/refile/backend_macros.rb +45 -0
- data/lib/refile/custom_logger.rb +48 -0
- data/lib/refile/file.rb +102 -0
- data/lib/refile/file_double.rb +13 -0
- data/lib/refile/image_processing.rb +1 -0
- data/lib/refile/rails.rb +54 -0
- data/lib/refile/rails/attachment_helper.rb +121 -0
- data/lib/refile/random_hasher.rb +11 -0
- data/lib/refile/signature.rb +36 -0
- data/lib/refile/simple_form.rb +17 -0
- data/lib/refile/type.rb +28 -0
- data/lib/refile/version.rb +3 -0
- data/spec/refile/active_record_helper.rb +35 -0
- data/spec/refile/app_spec.rb +424 -0
- data/spec/refile/attachment/active_record_spec.rb +568 -0
- data/spec/refile/attachment_helper_spec.rb +78 -0
- data/spec/refile/attachment_spec.rb +589 -0
- data/spec/refile/backend/file_system_spec.rb +5 -0
- data/spec/refile/backend_examples.rb +228 -0
- data/spec/refile/backend_macros_spec.rb +83 -0
- data/spec/refile/custom_logger_spec.rb +21 -0
- data/spec/refile/features/direct_upload_spec.rb +63 -0
- data/spec/refile/features/multiple_upload_spec.rb +122 -0
- data/spec/refile/features/normal_upload_spec.rb +144 -0
- data/spec/refile/features/presigned_upload_spec.rb +31 -0
- data/spec/refile/features/simple_form_spec.rb +8 -0
- data/spec/refile/fixtures/hello.txt +1 -0
- data/spec/refile/fixtures/image.jpg +0 -0
- data/spec/refile/fixtures/large.txt +44 -0
- data/spec/refile/fixtures/monkey.txt +1 -0
- data/spec/refile/fixtures/world.txt +1 -0
- data/spec/refile/spec_helper.rb +72 -0
- data/spec/refile_spec.rb +355 -0
- metadata +143 -0
@@ -0,0 +1,568 @@
|
|
1
|
+
require "refile/active_record_helper"
|
2
|
+
require "refile/attachment/active_record"
|
3
|
+
|
4
|
+
describe Refile::ActiveRecord::Attachment do
|
5
|
+
let(:options) { {} }
|
6
|
+
let(:required) { false }
|
7
|
+
let(:klass) do
|
8
|
+
opts = options
|
9
|
+
req = required
|
10
|
+
Class.new(ActiveRecord::Base) do
|
11
|
+
self.table_name = :posts
|
12
|
+
|
13
|
+
def self.name
|
14
|
+
"Post"
|
15
|
+
end
|
16
|
+
|
17
|
+
attachment :document, **opts
|
18
|
+
validates_presence_of :document, if: -> { req }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#valid?" do
|
23
|
+
let(:options) { { type: :image, cache: :limited_cache } }
|
24
|
+
|
25
|
+
context "extension validation" do
|
26
|
+
let(:options) { { cache: :limited_cache, extension: %w[Png] } }
|
27
|
+
|
28
|
+
context "with file" do
|
29
|
+
let(:options) { { cache: :limited_cache, extension: %w[Png Gif] } }
|
30
|
+
|
31
|
+
it "returns true when extension is included in list" do
|
32
|
+
post = klass.new
|
33
|
+
post.document = Refile::FileDouble.new("hello", "image.Png")
|
34
|
+
expect(post.valid?).to be_truthy
|
35
|
+
expect(post.errors[:document]).to be_empty
|
36
|
+
end
|
37
|
+
|
38
|
+
it "returns true when extension is included in list but chars are randomcase" do
|
39
|
+
post = klass.new
|
40
|
+
post.document = Refile::FileDouble.new("hello", "image.PNG")
|
41
|
+
expect(post.valid?).to be_truthy
|
42
|
+
expect(post.errors[:document]).to be_empty
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns false and an error message when extension is invalid" do
|
46
|
+
post = klass.new
|
47
|
+
post.document = Refile::FileDouble.new("hello", "image.jpg")
|
48
|
+
expect(post.valid?).to be_falsy
|
49
|
+
expect(post.errors[:document]).to match_array([/not allowed to upload jpg.+Allowed types: Png[^,]?/])
|
50
|
+
end
|
51
|
+
|
52
|
+
it "returns false and an error message when extension is empty" do
|
53
|
+
post = klass.new
|
54
|
+
post.document = Refile::FileDouble.new("hello", "image")
|
55
|
+
expect(post.valid?).to be_falsy
|
56
|
+
expect(post.errors[:document]).to match_array([/not allowed to upload an empty.+Allowed types: Png[^,]?/])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "with metadata" do
|
61
|
+
it "returns true when extension is included in list" do
|
62
|
+
file = Refile.cache.upload(StringIO.new("hello"))
|
63
|
+
post = klass.new
|
64
|
+
post.document = { id: file.id, filename: "image.Png", size: file.size }.to_json
|
65
|
+
expect(post.valid?).to be_truthy
|
66
|
+
expect(post.errors[:document]).to be_empty
|
67
|
+
end
|
68
|
+
|
69
|
+
it "returns true when extension is included in list but chars are randomcase" do
|
70
|
+
file = Refile.cache.upload(StringIO.new("hello"))
|
71
|
+
post = klass.new
|
72
|
+
post.document = { id: file.id, filename: "image.PNG", size: file.size }.to_json
|
73
|
+
expect(post.valid?).to be_truthy
|
74
|
+
expect(post.errors[:document]).to be_empty
|
75
|
+
end
|
76
|
+
|
77
|
+
it "returns false and an error message when extension is invalid" do
|
78
|
+
file = Refile.cache.upload(StringIO.new("hello"))
|
79
|
+
post = klass.new
|
80
|
+
post.document = { id: file.id, filename: "image.gif", size: file.size }.to_json
|
81
|
+
expect(post.valid?).to be_falsy
|
82
|
+
expect(post.errors[:document]).to match_array([/not allowed to upload gif.+Allowed types: Png[^,]?/])
|
83
|
+
end
|
84
|
+
|
85
|
+
it "returns false and an error message when extension is empty" do
|
86
|
+
file = Refile.cache.upload(StringIO.new("hello"))
|
87
|
+
post = klass.new
|
88
|
+
post.document = { id: file.id, filename: "image", size: file.size }.to_json
|
89
|
+
expect(post.valid?).to be_falsy
|
90
|
+
expect(post.errors[:document]).to match_array([/not allowed to upload an empty.+Allowed types: Png[^,]?/])
|
91
|
+
end
|
92
|
+
|
93
|
+
it "returns false when file size is zero" do
|
94
|
+
file = Refile.cache.upload(StringIO.new("hello"))
|
95
|
+
post = klass.new
|
96
|
+
post.document = { id: file.id, filename: "image.Png" }.to_json
|
97
|
+
expect(post.valid?).to be_falsy
|
98
|
+
expect(post.errors[:document].length).to eq(1)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "extension as Proc" do
|
103
|
+
context "Proc returns an array with extensions" do
|
104
|
+
let(:options) { { cache: :limited_cache, extension: -> { ["gif"] } } }
|
105
|
+
|
106
|
+
it "returns true when extension is included in list" do
|
107
|
+
post = klass.new
|
108
|
+
post.document = Refile::FileDouble.new("hello", "funny.gif")
|
109
|
+
expect(post.valid?).to be_truthy
|
110
|
+
expect(post.errors[:document]).to be_empty
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "Proc returns nil" do
|
115
|
+
let(:options) { { cache: :limited_cache, extension: -> {} } }
|
116
|
+
|
117
|
+
it "returns true when extension is included in list" do
|
118
|
+
post = klass.new
|
119
|
+
post.document = Refile::FileDouble.new("hello", "funny.gif")
|
120
|
+
expect(post.valid?).to be_falsey
|
121
|
+
expect(post.errors[:document].length).to eq(1)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context "with file" do
|
128
|
+
it "returns true when no file is assigned" do
|
129
|
+
post = klass.new
|
130
|
+
expect(post.valid?).to be_truthy
|
131
|
+
expect(post.errors[:document]).to be_empty
|
132
|
+
end
|
133
|
+
|
134
|
+
it "returns false and an error message when type is invalid" do
|
135
|
+
post = klass.new
|
136
|
+
post.document = Refile::FileDouble.new("hello", content_type: "text/plain")
|
137
|
+
expect(post.valid?).to be_falsy
|
138
|
+
expect(post.errors[:document]).to match_array(
|
139
|
+
[%r{not allowed to upload text/plain.+Allowed types: image/jpeg, image/gif, and image/png[^,]?}]
|
140
|
+
)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "returns false and an error message when type is empty" do
|
144
|
+
post = klass.new
|
145
|
+
post.document = Refile::FileDouble.new("hello", content_type: "")
|
146
|
+
expect(post.valid?).to be_falsy
|
147
|
+
expect(post.errors[:document]).to match_array(
|
148
|
+
[%r{not allowed to upload an empty.+Allowed types: image/jpeg, image/gif, and image/png[^,]?}]
|
149
|
+
)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "returns false and error messages when it has multiple errors" do
|
153
|
+
post = klass.new
|
154
|
+
post.document = Refile::FileDouble.new("h" * 200, content_type: "text/plain")
|
155
|
+
expect(post.valid?).to be_falsy
|
156
|
+
expect(post.errors[:document]).to match_array(
|
157
|
+
[
|
158
|
+
%r{not allowed to upload text/plain.+Allowed types: image/jpeg, image/gif, and image/png[^,]?},
|
159
|
+
"is too large"
|
160
|
+
]
|
161
|
+
)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "returns true when type is valid" do
|
165
|
+
post = klass.new
|
166
|
+
post.document = Refile::FileDouble.new("hello", content_type: "image/png")
|
167
|
+
expect(post.valid?).to be_truthy
|
168
|
+
expect(post.errors[:document]).to be_empty
|
169
|
+
end
|
170
|
+
|
171
|
+
it "returns true when an encoding is appended to a valid type" do
|
172
|
+
post = klass.new
|
173
|
+
post.document = Refile::FileDouble.new("hello", content_type: "image/png;charset=UTF-8")
|
174
|
+
expect(post.valid?).to be_truthy
|
175
|
+
expect(post.errors[:document]).to be_empty
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "when file is required" do
|
180
|
+
let(:required) { true }
|
181
|
+
let(:options) { {} }
|
182
|
+
|
183
|
+
it "returns false without file" do
|
184
|
+
post = klass.new
|
185
|
+
expect(post.valid?).to be_falsy
|
186
|
+
end
|
187
|
+
|
188
|
+
it "returns true with file" do
|
189
|
+
post = klass.new
|
190
|
+
post.document = Refile::FileDouble.new("hello", "image.png")
|
191
|
+
expect(post.valid?).to be_truthy
|
192
|
+
end
|
193
|
+
|
194
|
+
it "returns false when nil is assigned after a file" do
|
195
|
+
post = klass.new
|
196
|
+
post.document = Refile::FileDouble.new("hello", "image.png")
|
197
|
+
post.document = nil
|
198
|
+
expect(post.valid?).to be_falsy
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context "with metadata" do
|
203
|
+
it "returns false when metadata doesn't have an id" do
|
204
|
+
file = Refile.cache.upload(StringIO.new("hello"))
|
205
|
+
post = klass.new
|
206
|
+
post.document = { content_type: "text/png", size: file.size }.to_json
|
207
|
+
expect(post.valid?).to be_falsy
|
208
|
+
expect(post.errors[:document]).to match_array([%r{not allowed to upload text/png.+Allowed types: image/jpeg, image/gif, and image/png[^,]?}])
|
209
|
+
end
|
210
|
+
|
211
|
+
it "returns false and an error message when type is invalid" do
|
212
|
+
file = Refile.cache.upload(StringIO.new("hello"))
|
213
|
+
post = klass.new
|
214
|
+
post.document = { id: file.id, content_type: "text/png", size: file.size }.to_json
|
215
|
+
expect(post.valid?).to be_falsy
|
216
|
+
expect(post.errors[:document]).to match_array([%r{not allowed to upload text/png.+Allowed types: image/jpeg, image/gif, and image/png[^,]?}])
|
217
|
+
end
|
218
|
+
|
219
|
+
it "returns false and an error message when type is empty" do
|
220
|
+
file = Refile.cache.upload(StringIO.new("hello"))
|
221
|
+
post = klass.new
|
222
|
+
post.document = { id: file.id, content_type: "", size: file.size }.to_json
|
223
|
+
expect(post.valid?).to be_falsy
|
224
|
+
expect(post.errors[:document]).to match_array([%r{not allowed to upload an empty.+Allowed types: image/jpeg, image/gif, and image/png[^,]?}])
|
225
|
+
end
|
226
|
+
|
227
|
+
it "returns false when file size is zero" do
|
228
|
+
file = Refile.cache.upload(StringIO.new(""))
|
229
|
+
post = klass.new
|
230
|
+
post.document = { id: file.id, content_type: "image/png", size: file.size }.to_json
|
231
|
+
expect(post.valid?).to be_falsy
|
232
|
+
expect(post.errors[:document].length).to eq(1)
|
233
|
+
end
|
234
|
+
|
235
|
+
it "returns true when type is valid" do
|
236
|
+
file = Refile.cache.upload(StringIO.new("hello"))
|
237
|
+
post = klass.new
|
238
|
+
post.document = { id: file.id, content_type: "image/png", size: file.size }.to_json
|
239
|
+
expect(post.valid?).to be_truthy
|
240
|
+
expect(post.errors[:document]).to be_empty
|
241
|
+
end
|
242
|
+
|
243
|
+
it "returns true when an encoding is appended to a valid type" do
|
244
|
+
file = Refile.cache.upload(StringIO.new("hello"))
|
245
|
+
post = klass.new
|
246
|
+
post.document = { id: file.id, content_type: "image/png;charset=UTF-8", size: file.size }.to_json
|
247
|
+
expect(post.valid?).to be_truthy
|
248
|
+
expect(post.errors[:document]).to be_empty
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
describe "#save" do
|
254
|
+
it "stores the assigned file" do
|
255
|
+
post = klass.new
|
256
|
+
post.document = Refile::FileDouble.new("hello")
|
257
|
+
post.save
|
258
|
+
post = klass.find(post.id)
|
259
|
+
expect(post.document.read).to eq("hello")
|
260
|
+
expect(Refile.store.read(post.document.id)).to eq("hello")
|
261
|
+
end
|
262
|
+
|
263
|
+
it "replaces an existing file" do
|
264
|
+
post = klass.new
|
265
|
+
post.document = Refile::FileDouble.new("hello")
|
266
|
+
post.save
|
267
|
+
old_document = post.document
|
268
|
+
|
269
|
+
post = klass.find(post.id)
|
270
|
+
post.document = Refile::FileDouble.new("hello")
|
271
|
+
post.save
|
272
|
+
|
273
|
+
expect(Refile.store.read(post.document.id)).to eq("hello")
|
274
|
+
expect(post.document.id).not_to be eq old_document.id
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
describe "#destroy" do
|
279
|
+
context "default behaviour" do
|
280
|
+
it "removes the stored file" do
|
281
|
+
post = klass.new
|
282
|
+
post.document = Refile::FileDouble.new("hello")
|
283
|
+
post.save
|
284
|
+
file = post.document
|
285
|
+
post.destroy
|
286
|
+
expect(file.exists?).to be_falsy
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
context "with destroy: true" do
|
291
|
+
let(:options) { { destroy: true } }
|
292
|
+
|
293
|
+
it "removes the stored file" do
|
294
|
+
post = klass.new
|
295
|
+
post.document = Refile::FileDouble.new("hello")
|
296
|
+
post.save
|
297
|
+
file = post.document
|
298
|
+
post.destroy
|
299
|
+
expect(file.exists?).to be_falsy
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
context "with destroy: false" do
|
304
|
+
let(:options) { { destroy: false } }
|
305
|
+
|
306
|
+
it "does not remove the stored file" do
|
307
|
+
post = klass.new
|
308
|
+
post.document = Refile::FileDouble.new("hello")
|
309
|
+
post.save
|
310
|
+
file = post.document
|
311
|
+
post.destroy
|
312
|
+
expect(file.exists?).to be_truthy
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
describe ".accepts_nested_attributes_for" do
|
318
|
+
let(:options) { {} }
|
319
|
+
let(:post_class) do
|
320
|
+
opts = options
|
321
|
+
foo = document_class
|
322
|
+
Class.new(ActiveRecord::Base) do
|
323
|
+
self.table_name = :posts
|
324
|
+
|
325
|
+
def self.name
|
326
|
+
"Post"
|
327
|
+
end
|
328
|
+
|
329
|
+
has_many :documents, anonymous_class: foo, dependent: :destroy
|
330
|
+
accepts_attachments_for :documents, **opts
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
let(:document_class) do
|
335
|
+
Class.new(ActiveRecord::Base) do
|
336
|
+
self.table_name = :documents
|
337
|
+
|
338
|
+
def self.name
|
339
|
+
"Document"
|
340
|
+
end
|
341
|
+
|
342
|
+
attachment :file
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
let(:post) { post_class.new }
|
347
|
+
|
348
|
+
describe "#:association_:name" do
|
349
|
+
let(:wrong_method) { "files" }
|
350
|
+
let(:wrong_association_message) do
|
351
|
+
"wrong association name #{wrong_method}, use like this documents_files"
|
352
|
+
end
|
353
|
+
|
354
|
+
it "returns a friendly error message for wrong association name" do
|
355
|
+
expect { post.send(wrong_method) }.to raise_error(wrong_association_message)
|
356
|
+
end
|
357
|
+
|
358
|
+
it "return method missing" do
|
359
|
+
expect { post.foo }.to_not raise_error(wrong_association_message)
|
360
|
+
end
|
361
|
+
|
362
|
+
it "builds records from assigned files" do
|
363
|
+
post.documents_files = [Refile::FileDouble.new("hello"), Refile::FileDouble.new("world")]
|
364
|
+
expect(post.documents[0].file.read).to eq("hello")
|
365
|
+
expect(post.documents[1].file.read).to eq("world")
|
366
|
+
expect(post.documents.size).to eq(2)
|
367
|
+
end
|
368
|
+
|
369
|
+
it "builds records from cache" do
|
370
|
+
post.documents_files = [
|
371
|
+
[
|
372
|
+
{ id: Refile.cache.upload(Refile::FileDouble.new("hello")).id },
|
373
|
+
{ id: Refile.cache.upload(Refile::FileDouble.new("world")).id }
|
374
|
+
].to_json
|
375
|
+
]
|
376
|
+
expect(post.documents[0].file.read).to eq("hello")
|
377
|
+
expect(post.documents[1].file.read).to eq("world")
|
378
|
+
expect(post.documents.size).to eq(2)
|
379
|
+
end
|
380
|
+
|
381
|
+
it "prefers newly uploaded files over cache" do
|
382
|
+
post.documents_files = [
|
383
|
+
[
|
384
|
+
{ id: Refile.cache.upload(Refile::FileDouble.new("moo")).id }
|
385
|
+
].to_json,
|
386
|
+
Refile::FileDouble.new("hello"),
|
387
|
+
Refile::FileDouble.new("world")
|
388
|
+
]
|
389
|
+
expect(post.documents[0].file.read).to eq("hello")
|
390
|
+
expect(post.documents[1].file.read).to eq("world")
|
391
|
+
expect(post.documents.size).to eq(2)
|
392
|
+
end
|
393
|
+
|
394
|
+
it "clears previously assigned files" do
|
395
|
+
post.documents_files = [
|
396
|
+
Refile::FileDouble.new("hello"),
|
397
|
+
Refile::FileDouble.new("world")
|
398
|
+
]
|
399
|
+
post.save
|
400
|
+
post.update_attributes documents_files: [
|
401
|
+
Refile::FileDouble.new("foo")
|
402
|
+
]
|
403
|
+
retrieved = post_class.find(post.id)
|
404
|
+
expect(retrieved.documents[0].file.read).to eq("foo")
|
405
|
+
expect(retrieved.documents.size).to eq(1)
|
406
|
+
end
|
407
|
+
|
408
|
+
context "with append: true" do
|
409
|
+
let(:options) { { append: true } }
|
410
|
+
|
411
|
+
it "appends to previously assigned files" do
|
412
|
+
post.documents_files = [
|
413
|
+
Refile::FileDouble.new("hello"),
|
414
|
+
Refile::FileDouble.new("world")
|
415
|
+
]
|
416
|
+
post.save
|
417
|
+
post.update_attributes documents_files: [
|
418
|
+
Refile::FileDouble.new("foo")
|
419
|
+
]
|
420
|
+
retrieved = post_class.find(post.id)
|
421
|
+
expect(retrieved.documents[0].file.read).to eq("hello")
|
422
|
+
expect(retrieved.documents[1].file.read).to eq("world")
|
423
|
+
expect(retrieved.documents[2].file.read).to eq("foo")
|
424
|
+
expect(retrieved.documents.size).to eq(3)
|
425
|
+
end
|
426
|
+
|
427
|
+
it "appends to previously assigned files with cached files" do
|
428
|
+
post.documents_files = [
|
429
|
+
Refile::FileDouble.new("hello"),
|
430
|
+
Refile::FileDouble.new("world")
|
431
|
+
]
|
432
|
+
post.save
|
433
|
+
post.update_attributes documents_files: [
|
434
|
+
[{
|
435
|
+
id: Refile.cache.upload(Refile::FileDouble.new("hello")).id,
|
436
|
+
filename: "some.jpg",
|
437
|
+
content_type: "image/jpeg",
|
438
|
+
size: 1234
|
439
|
+
}].to_json
|
440
|
+
]
|
441
|
+
retrieved = post_class.find(post.id)
|
442
|
+
expect(retrieved.documents.size).to eq(3)
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
describe "#:association_:name_data" do
|
448
|
+
it "returns metadata of all files" do
|
449
|
+
post.documents_files = [nil, Refile::FileDouble.new("hello"), Refile::FileDouble.new("world")]
|
450
|
+
data = post.documents_files_data
|
451
|
+
expect(Refile.cache.read(data[0][:id])).to eq("hello")
|
452
|
+
expect(Refile.cache.read(data[1][:id])).to eq("world")
|
453
|
+
expect(data.size).to eq(2)
|
454
|
+
end
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
context "when attachment assigned to nested model" do
|
459
|
+
let(:base_users_class) do
|
460
|
+
Class.new(ActiveRecord::Base) do
|
461
|
+
self.table_name = :users
|
462
|
+
|
463
|
+
def self.name
|
464
|
+
"User"
|
465
|
+
end
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
context "when model has one nested attachment" do
|
470
|
+
let(:users_class) do
|
471
|
+
posts_class = klass
|
472
|
+
base_users_class.tap do |klass|
|
473
|
+
klass.instance_eval do
|
474
|
+
has_one :post, anonymous_class: posts_class
|
475
|
+
accepts_nested_attributes_for :post
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
describe "#save" do
|
481
|
+
it "stores the assigned file" do
|
482
|
+
user = users_class.create! post_attributes: { document: Refile::FileDouble.new("foo") }
|
483
|
+
|
484
|
+
post = user.post.reload
|
485
|
+
expect(post.document.read).to eq("foo")
|
486
|
+
expect(Refile.store.read(post.document.id)).to eq("foo")
|
487
|
+
end
|
488
|
+
|
489
|
+
it "removes files marked for removal" do
|
490
|
+
user = users_class.create!
|
491
|
+
post = klass.create!(user_id: user.id, document: Refile::FileDouble.new("foo"))
|
492
|
+
|
493
|
+
user.update_attributes!(post_attributes: { id: post.id, remove_document: true })
|
494
|
+
|
495
|
+
expect(post.reload.document).to be_nil
|
496
|
+
end
|
497
|
+
|
498
|
+
it "replaces an existing file" do
|
499
|
+
user = users_class.create! post_attributes: { document: Refile::FileDouble.new("foo") }
|
500
|
+
post = user.post
|
501
|
+
|
502
|
+
user.update! post_attributes: { id: post.id, document: Refile::FileDouble.new("bar") }
|
503
|
+
|
504
|
+
post.reload
|
505
|
+
expect(post.document.read).to eq("bar")
|
506
|
+
expect(Refile.store.read(post.document.id)).to eq("bar")
|
507
|
+
end
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
context "when model has many nested attachments" do
|
512
|
+
let(:users_class) do
|
513
|
+
posts_class = klass
|
514
|
+
base_users_class.tap do |klass|
|
515
|
+
klass.instance_eval do
|
516
|
+
has_many :posts, anonymous_class: posts_class
|
517
|
+
accepts_nested_attributes_for :posts
|
518
|
+
end
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
describe "#save" do
|
523
|
+
it "stores the assigned file" do
|
524
|
+
user = users_class.create! posts_attributes: [{ document: Refile::FileDouble.new("foo") }]
|
525
|
+
|
526
|
+
post = user.posts.first.reload
|
527
|
+
expect(post.document.read).to eq("foo")
|
528
|
+
expect(Refile.store.read(post.document.id)).to eq("foo")
|
529
|
+
end
|
530
|
+
|
531
|
+
it "removes files marked for removal" do
|
532
|
+
user = users_class.create!
|
533
|
+
post = klass.create!(user_id: user.id, document: Refile::FileDouble.new("foo"))
|
534
|
+
|
535
|
+
user.update_attributes!(posts_attributes: { id: post.id, remove_document: true })
|
536
|
+
|
537
|
+
expect(post.reload.document).to be_nil
|
538
|
+
end
|
539
|
+
|
540
|
+
it "replaces an existing file" do
|
541
|
+
user = users_class.create! posts_attributes: [{ document: Refile::FileDouble.new("foo") }]
|
542
|
+
post = user.posts.first
|
543
|
+
user.update! posts_attributes: [{ id: post.id, document: Refile::FileDouble.new("bar") }]
|
544
|
+
|
545
|
+
post.reload
|
546
|
+
expect(post.document.read).to eq("bar")
|
547
|
+
expect(Refile.store.read(post.document.id)).to eq("bar")
|
548
|
+
end
|
549
|
+
end
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
context "when assigned to an attribute that does not track changes" do
|
554
|
+
let(:klass) do
|
555
|
+
Class.new(ActiveRecord::Base) do
|
556
|
+
self.table_name = :posts
|
557
|
+
|
558
|
+
attachment :not_trackable_attribute
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
it "assigns the file to the attribute" do
|
563
|
+
post = klass.new
|
564
|
+
post.not_trackable_attribute = Refile::FileDouble.new("foo")
|
565
|
+
expect(post.not_trackable_attribute.read).to eq("foo")
|
566
|
+
end
|
567
|
+
end
|
568
|
+
end
|