citrusbyte-milton 0.1.8 → 0.1.9
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.
- 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