citrusbyte-milton 0.1.8 → 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/milton/attachment.rb +35 -28
- data/lib/milton/is_resizeable.rb +2 -2
- data/lib/milton/is_uploadable.rb +11 -13
- data/spec/milton/attachment_spec.rb +15 -0
- data/spec/milton/is_uploadable_spec.rb +13 -10
- data/spec/schema.rb +3 -0
- metadata +1 -1
data/lib/milton/attachment.rb
CHANGED
@@ -5,12 +5,18 @@ module Citrusbyte
|
|
5
5
|
module Milton
|
6
6
|
module Attachment
|
7
7
|
def self.included(base)
|
8
|
+
base.class_inheritable_accessor :milton_options
|
9
|
+
base.milton_options = {}
|
8
10
|
base.extend Citrusbyte::Milton::Attachment::AttachmentMethods
|
9
11
|
end
|
10
12
|
|
11
13
|
module AttachmentMethods
|
12
14
|
def has_attachment_methods(options={})
|
13
|
-
|
15
|
+
begin
|
16
|
+
raise "Milton requires a filename column on #{class_name} table" unless column_names.include?("filename")
|
17
|
+
rescue ActiveRecord::StatementInvalid => i
|
18
|
+
# table doesn't exist yet, i.e. hasn't been migrated in...
|
19
|
+
end
|
14
20
|
|
15
21
|
# character used to seperate a filename from its derivative options, this
|
16
22
|
# character will be stripped from all incoming filenames and replaced by
|
@@ -25,7 +31,7 @@ module Citrusbyte
|
|
25
31
|
# mode to set on stored files and created directories
|
26
32
|
options[:chmod] ||= 0755
|
27
33
|
|
28
|
-
|
34
|
+
self.milton_options.merge!(options)
|
29
35
|
|
30
36
|
validates_presence_of :filename
|
31
37
|
|
@@ -43,7 +49,7 @@ module Citrusbyte
|
|
43
49
|
# TODO: change the filename on the underlying file system on save so as
|
44
50
|
# not to orphan the file
|
45
51
|
def filename=(name)
|
46
|
-
write_attribute :filename, AttachableFile.sanitize_filename(name)
|
52
|
+
write_attribute :filename, AttachableFile.sanitize_filename(name, self.milton_options)
|
47
53
|
end
|
48
54
|
|
49
55
|
# Simple helper, same as path except returns the directory from
|
@@ -87,23 +93,21 @@ module Citrusbyte
|
|
87
93
|
# into your model, you get a reference to an AttachableFile (or something
|
88
94
|
# that extends AttachableFile).
|
89
95
|
class AttachableFile
|
90
|
-
class_inheritable_accessor :options
|
91
|
-
|
92
96
|
class << self
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
97
|
+
# Sanitizes the given filename, removes pathnames and the special chars
|
98
|
+
# needed for options seperation for derivatives
|
99
|
+
def sanitize_filename(filename, options)
|
100
|
+
File.basename(filename, File.extname(filename)).gsub(/^.*(\\|\/)/, '').
|
101
|
+
gsub(/[^\w]|#{Regexp.escape(options[:separator])}/, options[:replacement]).
|
102
|
+
strip + File.extname(filename)
|
103
|
+
end
|
100
104
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
105
|
+
# Creates the given directory and sets it to the mode given in
|
106
|
+
# options[:chmod]
|
107
|
+
def recreate_directory(directory, options)
|
108
|
+
FileUtils.mkdir_p(directory)
|
109
|
+
File.chmod(options[:chmod], directory)
|
110
|
+
end
|
107
111
|
|
108
112
|
# Partitioner that takes an id, pads it up to 12 digits then splits
|
109
113
|
# that into 4 folders deep, each 3 digits long.
|
@@ -132,6 +136,11 @@ module Citrusbyte
|
|
132
136
|
@attachment = attachment
|
133
137
|
@filename = filename
|
134
138
|
end
|
139
|
+
|
140
|
+
# Returns the milton options on the associated attachment.
|
141
|
+
def milton_options
|
142
|
+
self.attachment.class.milton_options
|
143
|
+
end
|
135
144
|
|
136
145
|
# Returns the full path and filename to the file with the given options.
|
137
146
|
# If no options are given then returns the path and filename to the
|
@@ -170,12 +179,12 @@ module Citrusbyte
|
|
170
179
|
|
171
180
|
# The full path to the root of where files will be stored on disk.
|
172
181
|
def root_path
|
173
|
-
|
182
|
+
milton_options[:file_system_path]
|
174
183
|
end
|
175
184
|
|
176
185
|
# Recreates the directory this file will be stored in.
|
177
186
|
def recreate_directory
|
178
|
-
self.class.recreate_directory(dirname) unless File.exists?(dirname)
|
187
|
+
self.class.recreate_directory(dirname, milton_options) unless File.exists?(dirname)
|
179
188
|
end
|
180
189
|
|
181
190
|
# Removes the containing directory from the filesystem (and hence the
|
@@ -217,13 +226,6 @@ module Citrusbyte
|
|
217
226
|
}).flatten]
|
218
227
|
end
|
219
228
|
|
220
|
-
# Merges the given options to build a derviative filename and returns
|
221
|
-
# the resulting filename.
|
222
|
-
def filename_for(filename, options={})
|
223
|
-
append = options.collect{ |k, v| "#{k}=#{v}" }.sort.join('_')
|
224
|
-
File.basename(filename, File.extname(filename)) + (append.blank? ? '' : "#{AttachableFile.options[:separator]}#{append}") + File.extname(filename)
|
225
|
-
end
|
226
|
-
|
227
229
|
# Given a filename (presumably with options embedded in it) parses out
|
228
230
|
# the options and returns them as a hash.
|
229
231
|
def extract_options_from(filename)
|
@@ -247,7 +249,12 @@ module Citrusbyte
|
|
247
249
|
|
248
250
|
# The resulting filename of this Derivative with embedded options.
|
249
251
|
def filename
|
250
|
-
|
252
|
+
filename = @file.path
|
253
|
+
append = options.collect{ |k, v| "#{k}=#{v}" }.sort.join('_')
|
254
|
+
|
255
|
+
File.basename(filename, File.extname(filename)) +
|
256
|
+
(append.blank? ? '' : "#{@file.milton_options[:separator]}#{append}") +
|
257
|
+
File.extname(filename)
|
251
258
|
end
|
252
259
|
|
253
260
|
# The full path and filename to this Derivative.
|
data/lib/milton/is_resizeable.rb
CHANGED
@@ -11,8 +11,8 @@ module Citrusbyte
|
|
11
11
|
|
12
12
|
ensure_attachment_methods options
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
self.milton_options.merge!(options)
|
15
|
+
|
16
16
|
extend Citrusbyte::Milton::IsResizeable::ClassMethods
|
17
17
|
include Citrusbyte::Milton::IsResizeable::InstanceMethods
|
18
18
|
end
|
data/lib/milton/is_uploadable.rb
CHANGED
@@ -6,20 +6,18 @@ module Citrusbyte
|
|
6
6
|
end
|
7
7
|
|
8
8
|
module IsMethods
|
9
|
-
def is_uploadable(options = {})
|
10
|
-
raise "Milton's is_uploadable requires a filename column on #{class_name} table" unless column_names.include?("filename")
|
11
|
-
|
9
|
+
def is_uploadable(options = {})
|
12
10
|
# TODO: implement size validations
|
13
11
|
# options[:min_size] ||= 1
|
14
12
|
# options[:max_size] ||= 4.megabytes
|
15
13
|
# options[:size] ||= (options[:min_size]..options[:max_size])
|
16
14
|
|
17
|
-
options[:tempfile_path] ||= File.join(RAILS_ROOT, "tmp", "milton")
|
18
|
-
|
19
15
|
ensure_attachment_methods options
|
20
|
-
|
21
|
-
UploadableFile.options = AttachableFile.options.merge(options)
|
22
16
|
|
17
|
+
options[:tempfile_path] ||= File.join(RAILS_ROOT, "tmp", "milton")
|
18
|
+
|
19
|
+
self.milton_options.merge!(options)
|
20
|
+
|
23
21
|
after_create :save_uploaded_file
|
24
22
|
|
25
23
|
extend Citrusbyte::Milton::IsUploadable::ClassMethods
|
@@ -77,10 +75,10 @@ module Citrusbyte
|
|
77
75
|
attr_reader :content_type, :filename, :size
|
78
76
|
|
79
77
|
class << self
|
80
|
-
def write_to_temp_file(data_or_path)
|
81
|
-
FileUtils.mkdir_p(
|
78
|
+
def write_to_temp_file(data_or_path, options)
|
79
|
+
FileUtils.mkdir_p(options[:tempfile_path]) unless File.exists?(options[:tempfile_path])
|
82
80
|
|
83
|
-
tempfile = Tempfile.new("#{rand(Time.now.to_i)}",
|
81
|
+
tempfile = Tempfile.new("#{rand(Time.now.to_i)}", options[:tempfile_path])
|
84
82
|
|
85
83
|
if data_or_path.is_a?(StringIO)
|
86
84
|
tempfile.binmode
|
@@ -98,8 +96,8 @@ module Citrusbyte
|
|
98
96
|
def initialize(attachment, data_or_path)
|
99
97
|
@has_been_saved = false
|
100
98
|
@content_type = data_or_path.content_type
|
101
|
-
@filename = AttachableFile.sanitize_filename(data_or_path.original_filename) if respond_to?(:filename)
|
102
|
-
@tempfile = UploadableFile.write_to_temp_file(data_or_path)
|
99
|
+
@filename = AttachableFile.sanitize_filename(data_or_path.original_filename, attachment.class.milton_options) if respond_to?(:filename)
|
100
|
+
@tempfile = UploadableFile.write_to_temp_file(data_or_path, attachment.class.milton_options)
|
103
101
|
@size = File.size(self.temp_path)
|
104
102
|
|
105
103
|
super attachment, filename
|
@@ -113,7 +111,7 @@ module Citrusbyte
|
|
113
111
|
return true if self.saved?
|
114
112
|
recreate_directory
|
115
113
|
File.cp(temp_path, path)
|
116
|
-
File.chmod(
|
114
|
+
File.chmod(milton_options[:chmod], path)
|
117
115
|
@has_been_saved = true
|
118
116
|
end
|
119
117
|
|
@@ -1,6 +1,21 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
3
|
describe Attachment do
|
4
|
+
describe "setting options" do
|
5
|
+
before :each do
|
6
|
+
Attachment.class_eval("is_uploadable :file_system_path => 'foo'")
|
7
|
+
Image.class_eval("is_uploadable :file_system_path => 'bar'")
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should not overwrite Attachment's file_system_path setting with Image's" do
|
11
|
+
Attachment.milton_options[:file_system_path].should eql('foo')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should not overwrite Image's file_system_path setting with Attachment's" do
|
15
|
+
Image.milton_options[:file_system_path].should eql('bar')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
4
19
|
describe "being destroyed" do
|
5
20
|
before :each do
|
6
21
|
@attachment = Attachment.create :file => upload('milton.jpg')
|
@@ -4,28 +4,31 @@ describe Citrusbyte::Milton::IsUploadable do
|
|
4
4
|
class NotUploadable < ActiveRecord::Base
|
5
5
|
end
|
6
6
|
|
7
|
+
class NoTable < ActiveRecord::Base
|
8
|
+
end
|
9
|
+
|
7
10
|
describe "filename column" do
|
11
|
+
it 'should not raise an exception if there is a filename column' do
|
12
|
+
lambda { Attachment.class_eval("is_uploadable") }.should_not raise_error
|
13
|
+
end
|
14
|
+
|
8
15
|
it "should raise an exception if there is no filename column" do
|
9
16
|
lambda { NotUploadable.class_eval("is_uploadable") }.should raise_error
|
10
17
|
end
|
11
|
-
|
12
|
-
it 'should not raise an exception if
|
13
|
-
lambda {
|
18
|
+
|
19
|
+
it 'should not raise an exception if the underlying table doesn\'t exist' do
|
20
|
+
lambda { NoTable.class_eval('is_uploadable') }.should_not raise_error
|
14
21
|
end
|
15
22
|
end
|
16
23
|
|
17
24
|
describe "setting :file_system_path" do
|
18
25
|
it "should allow options to be accessed" do
|
19
|
-
|
26
|
+
Attachment.milton_options.should be_kind_of(Hash)
|
20
27
|
end
|
21
28
|
|
22
29
|
it "should be able to overwrite file_system_path from is_uploadable call" do
|
23
30
|
Attachment.class_eval("is_uploadable(:file_system_path => 'foo')")
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
after :all do
|
28
|
-
Citrusbyte::Milton::UploadableFile.options[:file_system_path] = File.join(File.dirname(__FILE__), '..', 'output')
|
31
|
+
Attachment.milton_options[:file_system_path].should eql('foo')
|
29
32
|
end
|
30
33
|
end
|
31
34
|
|
@@ -70,7 +73,7 @@ describe Citrusbyte::Milton::IsUploadable do
|
|
70
73
|
end
|
71
74
|
|
72
75
|
it "should use set file_system_path" do
|
73
|
-
@attachment.path.should =~ /^#{
|
76
|
+
@attachment.path.should =~ /^#{@attachment.milton_options[:file_system_path]}.*$/
|
74
77
|
end
|
75
78
|
|
76
79
|
it "should use uploaded filename" do
|
data/spec/schema.rb
CHANGED