citrusbyte-milton 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Alavi
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-02-16 00:00:00 -08:00
12
+ date: 2008-04-25 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -21,31 +21,10 @@ extensions: []
21
21
 
22
22
  extra_rdoc_files: []
23
23
 
24
- files:
25
- - INSTALL
26
- - MIT-LICENSE
27
- - README
28
- - CHANGELOG.rdoc
29
- - init.rb
30
- - lib/milton.rb
31
- - lib/milton/attachment.rb
32
- - lib/milton/is_image.rb
33
- - lib/milton/is_resizeable.rb
34
- - lib/milton/is_uploadable.rb
35
- - spec/schema.rb
36
- - spec/spec.opts
37
- - spec/spec_helper.rb
38
- - spec/fixtures/big-milton.jpg
39
- - spec/fixtures/milton.jpg
40
- - spec/fixtures/mini-milton.jpg
41
- - spec/fixtures/unsanitary .milton.jpg
42
- - spec/milton/attachment_spec.rb
43
- - spec/milton/is_image_spec.rb
44
- - spec/milton/is_resizeable_spec.rb
45
- - spec/milton/is_uploadable_spec.rb
46
- - spec/milton/milton_spec.rb
24
+ files: []
25
+
47
26
  has_rdoc: true
48
- homepage: http://labs.citrusbyte.com/milton
27
+ homepage: http://labs.citrusbyte.com/projects/milton
49
28
  post_install_message:
50
29
  rdoc_options: []
51
30
 
@@ -69,6 +48,6 @@ rubyforge_project:
69
48
  rubygems_version: 1.2.0
70
49
  signing_key:
71
50
  specification_version: 2
72
- summary: Asset handling Rails plugin that makes few assumptions and is highly extensible.
51
+ summary: Rails file and upload handling plugin built for extensibility. Supports Amazon S3 and resizes images.
73
52
  test_files: []
74
53
 
@@ -1,22 +0,0 @@
1
- == 0.2.4, released 2009-02-16
2
-
3
- * Got rid of symlink_aware_mkdir_p as it wasn't actually needed, problem was
4
- caused by invalid symlinks in the first place, oops. Left specs as they are
5
- still valid.
6
-
7
- == 0.2.3, released 2009-02-16
8
-
9
- * Added a symlink_aware_mkdir_p to FileUtils to actually fix problem w/ root
10
- attachments path being a symlink.
11
- * Added specs to reproduce error and fix in attachment_spec.rb
12
-
13
- == 0.2.2, released 2009-02-16
14
-
15
- * Made recreate directories aware of symlinks to avoid trying to recreate the
16
- folder attachments are stored in if it's a symlink
17
-
18
- == 0.2.1, released 2009-01-16
19
-
20
- * Fixed init.rb to work as a gem
21
- * Altered gemspec a tad
22
- * Started CHANGELOG
data/INSTALL DELETED
@@ -1,26 +0,0 @@
1
- == Installing Milton
2
-
3
- GemPlugin (Rails 2.1+)
4
- -------------------------------------------------------------------------------
5
-
6
- Add to your environment.rb:
7
-
8
- config.gem "citrusbyte-milton", :source => "http://gems.github.com", :lib => "milton"
9
-
10
- Then run "rake gems:install" to install the gem.
11
-
12
- Plugin
13
- -------------------------------------------------------------------------------
14
-
15
- script/plugin install git://github.com/citrusbyte/milton.git
16
-
17
- Gem
18
- -------------------------------------------------------------------------------
19
-
20
- gem install citrusbyte-milton --source http://gems.github.com
21
-
22
- == Installing ImageMagick (for image resizing)
23
-
24
- == Installing a FileSystem
25
-
26
- ...j/k j/k
@@ -1,20 +0,0 @@
1
- Copyright (c) 2008 Citrusbyte, LLC
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README DELETED
@@ -1,18 +0,0 @@
1
- == Milton
2
-
3
- Milton is an extensible attachment handling plugin that makes few assumptions
4
- but provides a lot of power.
5
-
6
- == More Info
7
-
8
- http://labs.citrusbyte.com/milton
9
-
10
- http://github.com/citrusbyte/milton/wikis/home
11
-
12
- == Dependencies
13
- * ActiveRecord
14
- * Rails (for now?)
15
- * A filesystem (more storage solutions coming soon...)
16
-
17
- === For Image manipulation (not required!)
18
- * ImageMagick (more processors coming soon)
data/init.rb DELETED
@@ -1 +0,0 @@
1
- require 'milton'
@@ -1,78 +0,0 @@
1
- require 'milton/attachment'
2
- require 'milton/is_image'
3
- require 'milton/is_resizeable'
4
- require 'milton/is_uploadable'
5
-
6
- module Citrusbyte
7
- module Milton
8
- # Raised when a file which was expected to exist appears not to exist
9
- class MissingFileError < StandardError;end;
10
-
11
- # Some definitions for file semantics used throughout Milton, understanding
12
- # this will make understanding the code a bit easier and avoid ambiguity:
13
- #
14
- # path:
15
- # the full path to a file or directory in the filesystem
16
- # /var/log/apache2 or /var/log/apache2/access.log
17
- # can also be defined as:
18
- # path == dirname + filename
19
- # path == dirname + basename + extension
20
- #
21
- # dirname:
22
- # the directory portion of the path to a file or directory, all the chars
23
- # up to the final /
24
- # /var/log/apache2 => /var/log
25
- # /var/log/apache2/ => /var/log/apache2
26
- # /var/log/apache2/access.log => /var/log/apache2
27
- #
28
- # basename:
29
- # the portion of a filename *with no extension* (ruby's "basename" may or
30
- # may not have an extension), all the chars after the last / and before
31
- # the last .
32
- # /var/log/apache2 => apache2
33
- # /var/log/apache2/ => nil
34
- # /var/log/apache2/access.log => access
35
- # /var/log/apache2/access.2008.log => access.2008
36
- #
37
- # extension:
38
- # the extension portion of a filename w/ no preceding ., all the chars
39
- # after the final .
40
- # /var/log/apache2 => nil
41
- # /var/log/apache2/ => nil
42
- # /var/log/apache2/access.log => log
43
- # /var/log/apache2/access.2008.log => log
44
- #
45
- # filename:
46
- # the filename portion of a path w/ extension, all the chars after the
47
- # final /
48
- # /var/log/apache2 => apache2
49
- # /var/log/apache2/ => nil
50
- # /var/log/apache2/access.log => access.log
51
- # /var/log/apache2/access.2008.log => access.2008.log
52
- # can also be defined as:
53
- # filename == basename + (extension ? '.' + extension : '')
54
- #
55
-
56
- def self.included(base)
57
- base.extend Citrusbyte::Milton::BaseMethods
58
- base.extend Citrusbyte::Milton::IsUploadable::IsMethods
59
- base.extend Citrusbyte::Milton::IsResizeable::IsMethods
60
- base.extend Citrusbyte::Milton::IsImage::IsMethods
61
- end
62
-
63
- module BaseMethods
64
- protected
65
- # The attachment methods give the core of Milton's file-handling, so
66
- # various extensions can use this when they're included to make sure
67
- # that the core attachment methods are available
68
- def ensure_attachment_methods(options={})
69
- unless included_modules.include?(Citrusbyte::Milton::Attachment)
70
- include Citrusbyte::Milton::Attachment
71
- has_attachment_methods(options)
72
- end
73
- end
74
- end
75
- end
76
- end
77
-
78
- ActiveRecord::Base.send(:include, Citrusbyte::Milton)
@@ -1,278 +0,0 @@
1
- require 'ftools'
2
- require 'fileutils'
3
-
4
- module Citrusbyte
5
- module Milton
6
- module Attachment
7
- def self.included(base)
8
- base.class_inheritable_accessor :milton_options
9
- base.milton_options = {}
10
- base.extend Citrusbyte::Milton::Attachment::AttachmentMethods
11
- end
12
-
13
- module AttachmentMethods
14
- def require_column(column, message)
15
- begin
16
- raise message unless column_names.include?(column)
17
- rescue ActiveRecord::StatementInvalid => i
18
- # table doesn't exist yet, i.e. hasn't been migrated in...
19
- end
20
- end
21
-
22
- def has_attachment_methods(options={})
23
- require_column 'filename', "Milton requires a filename column on #{class_name} table"
24
-
25
- # character used to seperate a filename from its derivative options, this
26
- # character will be stripped from all incoming filenames and replaced by
27
- # replacement
28
- options[:separator] ||= '.'
29
- options[:replacement] ||= '-'
30
-
31
- # root of where the underlying files are stored (or will be stored)
32
- # on the file system
33
- options[:file_system_path] ||= File.join(RAILS_ROOT, "public", table_name)
34
-
35
- # mode to set on stored files and created directories
36
- options[:chmod] ||= 0755
37
-
38
- self.milton_options.merge!(options)
39
-
40
- validates_presence_of :filename
41
-
42
- before_destroy :destroy_attached_file
43
-
44
- include Citrusbyte::Milton::Attachment::InstanceMethods
45
- end
46
- end
47
-
48
- # These get mixed in to your model when you use Milton
49
- module InstanceMethods
50
- # Sets the filename to the given filename (sanitizes the given filename
51
- # as well)
52
- #
53
- # TODO: change the filename on the underlying file system on save so as
54
- # not to orphan the file
55
- def filename=(name)
56
- write_attribute :filename, AttachableFile.sanitize_filename(name, self.milton_options)
57
- end
58
-
59
- # Simple helper, same as path except returns the directory from
60
- # .../public/ on, i.e. for showing images in your views.
61
- #
62
- # @asset.path => /var/www/site/public/assets/000/000/001/313/milton.jpg
63
- # @asset.public_path => /assets/000/000/001/313/milton.jpg
64
- #
65
- # Can send a different base path than public if you want to give the
66
- # path from that base on, useful if you change your root path to
67
- # somewhere else.
68
- def public_path(options={}, base='public')
69
- path(options).gsub(/.*?\/#{base}/, '')
70
- end
71
-
72
- # The path to the file, takes an optional hash of options which can be
73
- # used to determine a particular derivative of the file desired
74
- def path(options={})
75
- attached_file.path(options)
76
- end
77
-
78
- protected
79
- # A reference to the attached file, this is probably what you want to
80
- # overwrite to introduce a new behavior
81
- #
82
- # i.e.
83
- # have attached_file return a ResizeableFile, or a TranscodableFile
84
- def attached_file
85
- @attached_file ||= AttachableFile.new(self, filename)
86
- end
87
-
88
- # Clean the file from the filesystem
89
- def destroy_attached_file
90
- attached_file.destroy
91
- end
92
- end
93
- end
94
-
95
- # AttachableFile is what Milton uses to interface between your model and
96
- # the underlying file. Rather than just pushing a whole bunch of methods
97
- # into your model, you get a reference to an AttachableFile (or something
98
- # that extends AttachableFile).
99
- class AttachableFile
100
- class << self
101
- # Sanitizes the given filename, removes pathnames and the special chars
102
- # needed for options seperation for derivatives
103
- def sanitize_filename(filename, options)
104
- File.basename(filename, File.extname(filename)).gsub(/^.*(\\|\/)/, '').
105
- gsub(/[^\w]|#{Regexp.escape(options[:separator])}/, options[:replacement]).
106
- strip + File.extname(filename)
107
- end
108
-
109
- # Creates the given directory and sets it to the mode given in
110
- # options[:chmod]
111
- def recreate_directory(directory, options)
112
- return true if File.exists?(directory)
113
- FileUtils.mkdir_p(directory)
114
- File.chmod(options[:chmod], directory)
115
- end
116
-
117
- # Partitioner that takes an id, pads it up to 12 digits then splits
118
- # that into 4 folders deep, each 3 digits long.
119
- #
120
- # i.e.
121
- # 000/000/012/139
122
- #
123
- # Scheme allows for 1000 billion files while never storing more than
124
- # 1000 files in a single folder.
125
- #
126
- # Can overwrite this method to provide your own partitioning scheme.
127
- def partition(id)
128
- # TODO: there's probably some fancy 1-line way to do this...
129
- padded = ("0"*(12-id.to_s.size)+id.to_s).split('')
130
- File.join(*[0, 3, 6, 9].collect{ |i| padded.slice(i, 3).join })
131
- end
132
- end
133
-
134
- attr_accessor :filename
135
- attr_accessor :attachment
136
-
137
- # TODO: can probably fanagle a way to only pass a reference to the model
138
- # and not need the filename (or better yet just the filename and
139
- # decouple)
140
- def initialize(attachment, filename)
141
- @attachment = attachment
142
- @filename = filename
143
- end
144
-
145
- # Returns the milton options on the associated attachment.
146
- def milton_options
147
- self.attachment.class.milton_options
148
- end
149
-
150
- # Returns the full path and filename to the file with the given options.
151
- # If no options are given then returns the path and filename to the
152
- # original file.
153
- def path(options={})
154
- options.empty? ? File.join(dirname, filename) : Derivative.new(filename, options).path
155
- end
156
-
157
- # Returns the full directory path up to the file, w/o the filename.
158
- def dirname
159
- File.join(root_path, partitioned_path)
160
- end
161
-
162
- # Returns true if the file exists on the underlying file system.
163
- def exists?
164
- File.exist?(path)
165
- end
166
-
167
- # Removes the file from the underlying file system and any derivatives of
168
- # the file.
169
- def destroy
170
- destroy_file
171
- end
172
-
173
- protected
174
- # Returns the file as a File object opened for reading.
175
- def file_reference
176
- File.new(path)
177
- end
178
-
179
- # Returns the partitioned path segment based on the id of the model
180
- # this file is attached to.
181
- def partitioned_path
182
- self.class.partition(self.attachment.id)
183
- end
184
-
185
- # The full path to the root of where files will be stored on disk.
186
- def root_path
187
- milton_options[:file_system_path]
188
- end
189
-
190
- # Creates the directory this file will be stored in.
191
- # Also creates the root path where all attachments are stored if it
192
- # doesn't exist yet.
193
- def recreate_directory
194
- self.class.recreate_directory(dirname, milton_options)
195
- end
196
-
197
- # Removes the containing directory from the filesystem (and hence the
198
- # file and any derivatives)
199
- def destroy_file
200
- FileUtils.rm_rf dirname if File.exists?(dirname)
201
- end
202
-
203
- # Returns an array of Derivatives of this AttachableFile.
204
- def derivatives
205
- Dir.glob(dirname + '/*').reject{ |filename| filename == self.filename }.collect do |filename|
206
- Derivative.from_filename(filename)
207
- end
208
- end
209
- end
210
-
211
- # Represents a file created on the file system that is a derivative of the
212
- # one referenced by the model, i.e. a thumbnail of an image, or a transcode
213
- # of a video.
214
- #
215
- # Provides a container for options and a uniform API to dealing with
216
- # passing options for the creation of derivatives.
217
- #
218
- # Files created as derivatives have their creation options appended into
219
- # their filenames so it can be checked later if a file w/ the given
220
- # options already exists (so as not to create it again).
221
- #
222
- class Derivative
223
- attr_reader :options
224
-
225
- class << self
226
- # Given a string of attachment options, splits them out into a hash,
227
- # useful for things that take options on the query string or from
228
- # filenames
229
- def options_from(string)
230
- Hash[*(string.split('_').collect { |option|
231
- key, value = option.split('=')
232
- [ key.to_sym, value ]
233
- }).flatten]
234
- end
235
-
236
- # Given a filename (presumably with options embedded in it) parses out
237
- # the options and returns them as a hash.
238
- def extract_options_from(filename)
239
- File.basename(filename, File.extname(filename))[(filename.rindex(AttachableFile.options[:separator]) + 1)..-1]
240
- end
241
-
242
- # Creates a new Derivative from the given filename by extracting the
243
- # options.
244
- def from_filename(filename)
245
- Derivative.new(filename, options_from(extract_options_from(filename)))
246
- end
247
- end
248
-
249
- # Instantiate a new Derivative, takes a reference to the AttachableFile
250
- # (or specialization class) that this will be a derivative of, and a hash
251
- # of the options defining the derivative.
252
- def initialize(file, options)
253
- @file = file
254
- @options = options
255
- end
256
-
257
- # The resulting filename of this Derivative with embedded options.
258
- def filename
259
- filename = @file.path
260
- append = options.collect{ |k, v| "#{k}=#{v}" }.sort.join('_')
261
-
262
- File.basename(filename, File.extname(filename)) +
263
- (append.blank? ? '' : "#{@file.milton_options[:separator]}#{append}") +
264
- File.extname(filename)
265
- end
266
-
267
- # The full path and filename to this Derivative.
268
- def path
269
- File.join(@file.dirname, filename)
270
- end
271
-
272
- # Returns true if the file resulting from this Derivative exists.
273
- def exists?
274
- File.exists?(path)
275
- end
276
- end
277
- end
278
- end