citrusbyte-milton 0.2.4 → 0.3.0

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.
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