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.
@@ -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
- raise "Milton requires a filename column on #{table_name} table" unless column_names.include?("filename")
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
- AttachableFile.options = options
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
- # Sanitizes the given filename, removes pathnames and the special chars
94
- # needed for options seperation for derivatives
95
- def sanitize_filename(filename)
96
- File.basename(filename, File.extname(filename)).gsub(/^.*(\\|\/)/, '').
97
- gsub(/[^\w]|#{Regexp.escape(options[:separator])}/, options[:replacement]).
98
- strip + File.extname(filename)
99
- end
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
- # Creates the given directory and sets it to the mode given in
102
- # options[:chmod]
103
- def recreate_directory(directory)
104
- FileUtils.mkdir_p(directory)
105
- File.chmod(options[:chmod], directory)
106
- end
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
- self.class.options[:file_system_path]
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
- self.class.filename_for(@file.path, options)
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.
@@ -11,8 +11,8 @@ module Citrusbyte
11
11
 
12
12
  ensure_attachment_methods options
13
13
 
14
- ResizeableFile.options = AttachableFile.options.merge(options)
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
@@ -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(self.options[:tempfile_path]) unless File.exists?(self.options[:tempfile_path])
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)}", self.options[:tempfile_path])
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(self.class.options[:chmod], path)
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 there is a filename column' do
13
- lambda { Attachment.class_eval("is_uploadable") }.should_not raise_error
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
- Citrusbyte::Milton::UploadableFile.options.should be_kind_of(Hash)
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
- Citrusbyte::Milton::UploadableFile.options[:file_system_path].should eql('foo')
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 =~ /^#{Citrusbyte::Milton::AttachableFile.options[:file_system_path]}.*$/
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
@@ -7,4 +7,7 @@ ActiveRecord::Schema.define :version => 0 do
7
7
  t.string :filename
8
8
  t.string :content_type
9
9
  end
10
+
11
+ create_table :not_uploadables, :force => true do |t|
12
+ end
10
13
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: citrusbyte-milton
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Alavi