attached 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/attached.rb CHANGED
@@ -65,6 +65,13 @@ module Attached
65
65
  attachment_for(name).file?
66
66
  end
67
67
 
68
+ validates_each(name) do |record, attr, value|
69
+ attachment = record.attachment_for(name)
70
+ attachment.errors.each do |error|
71
+ record.errors.add(name, error)
72
+ end
73
+ end
74
+
68
75
  after_validation do
69
76
 
70
77
  self.errors[:"#{name}_size"].each do |message|
@@ -128,6 +135,29 @@ module Attached
128
135
  end
129
136
 
130
137
 
138
+ # Validates an attached extension in a specified set.
139
+ #
140
+ # Options:
141
+ #
142
+ # * :in - allowed values for attached
143
+ #
144
+ # Usage:
145
+ #
146
+ # validates_attached_extension :avatar, :in => %w(png jpg)
147
+ # validates_attached_extension :avatar, :in => [:png, :jpg]
148
+ # validates_attached_extension :avatar, :in => %w(png jpg), :message => "extension must be :in"
149
+ # validates_attached_extension :avatar, :in => %w(png jpg), :message => "extension must be :in"
150
+
151
+ def validates_attached_extension(name, options = {})
152
+
153
+ message = options[:message]
154
+ message ||= "extension must be specified"
155
+
156
+ range = options[:in].map { |element| /element/ }
157
+
158
+ end
159
+
160
+
131
161
  # Validates that an attachment is included.
132
162
  #
133
163
  # Options:
@@ -1,8 +1,10 @@
1
1
  require 'guid'
2
2
 
3
3
  require 'attached/storage'
4
+ require 'attached/storage/error'
5
+
4
6
  require 'attached/processor'
5
- require 'attached/image'
7
+ require 'attached/processor/error'
6
8
 
7
9
  module Attached
8
10
 
@@ -13,6 +15,7 @@ module Attached
13
15
  attr_reader :name
14
16
  attr_reader :instance
15
17
  attr_reader :queue
18
+ attr_reader :errors
16
19
  attr_reader :path
17
20
  attr_reader :styles
18
21
  attr_reader :default
@@ -66,6 +69,7 @@ module Attached
66
69
  @instance = instance
67
70
 
68
71
  @queue = {}
72
+ @errors = []
69
73
 
70
74
  @path = options[:path]
71
75
  @styles = options[:styles]
@@ -267,13 +271,18 @@ module Attached
267
271
 
268
272
  def process
269
273
  self.queue[self.default] = self.file
274
+
275
+ begin
270
276
 
271
- self.processors.each do |processor|
272
- self.styles.each do |style, options|
273
- case processor
274
- when :image then self.queue[style] = Attached::Image.process(self.queue[style] || self.file, options, self)
277
+ self.processors.each do |processor|
278
+ processor = Attached::Processor.processor(processor)
279
+ self.styles.each do |style, options|
280
+ self.queue[style] = processor.process(self.queue[style] || self.file, options, self)
275
281
  end
276
282
  end
283
+
284
+ rescue Attached::Processor::Error => error
285
+ self.errors << error.message
277
286
  end
278
287
  end
279
288
 
@@ -1,48 +1,32 @@
1
- module Attached
1
+ require 'attached/processor/base'
2
+ require 'attached/processor/audio'
3
+ require 'attached/processor/image'
2
4
 
3
- class Processor
4
-
5
-
6
- attr_accessor :file
7
- attr_accessor :options
8
- attr_accessor :attachment
5
+ module Attached
6
+ module Processor
9
7
 
10
8
 
11
- # Create and run a processor.
9
+ # Create a storage object given a medium and credentials.
12
10
  #
13
- # Parameters:
14
- #
15
- # * file - The file to be processed.
16
- # * options - The options to be applied to the processing.
17
- # * attachment - The attachment the processor is being run for.
18
-
19
- def self.process(file, options = {}, attachment = nil)
20
- new(file, options, attachment).process
21
- end
22
-
23
-
24
- # Create a processor.
11
+ # Usage:
25
12
  #
26
- # Parameters:
27
- #
28
- # * file - The file to be processed.
29
- # * options - The options to be applied to the processing.
30
- # * attachment - The attachment the processor is being run for.
31
-
32
- def initialize(file, options = {}, attachment = nil)
33
- @file = file
34
- @options = options
35
- @attachment = attachment
36
- end
37
-
38
-
39
- # Run the processor.
40
-
41
- def process
42
- raise NotImplementedError.new
13
+ # Attached::Processor.processor(:audio)
14
+ # Attached::Processor.processor(:image)
15
+ # Attached::Processor.processor(Attached::Processor::Video)
16
+
17
+ def self.processor(processor)
18
+
19
+ return processor if processor.is_a? Attached::Processor::Base
20
+
21
+ case processor
22
+ when :audio then return Attached::Processor::Audio
23
+ when :image then return Attached::Processor::Image
24
+ end
25
+
26
+ raise "undefined processor '#{processor}'"
27
+
43
28
  end
44
29
 
45
30
 
46
31
  end
47
-
48
- end
32
+ end
@@ -0,0 +1,72 @@
1
+ require 'attached/processor/base'
2
+ require 'attached/processor/error'
3
+
4
+ module Attached
5
+ module Processor
6
+ class Audio < Base
7
+
8
+
9
+ attr_reader :path
10
+ attr_reader :extension
11
+ attr_reader :preset
12
+
13
+
14
+ # Create a processor.
15
+ #
16
+ # Parameters:
17
+ #
18
+ # * file - The file to be processed.
19
+ # * options - The options to be applied to the processing.
20
+ # * attachment - The attachment the processor is being run for.
21
+
22
+ def initialize(file, options = {}, attachment = nil)
23
+ super
24
+
25
+ @path = self.file.path
26
+
27
+ @preset = options[:preset]
28
+ @extension = options[:extension]
29
+
30
+ @extension ||= File.extname(self.file.path)
31
+ end
32
+
33
+
34
+ # Helper function for calling processors.
35
+ #
36
+ # Usage:
37
+ #
38
+ # self.process
39
+
40
+ def process
41
+
42
+ result = Tempfile.new(["", self.extension])
43
+ result.binmode
44
+
45
+ begin
46
+
47
+ parameters = []
48
+
49
+ parameters << "--preset #{self.preset}" if self.preset
50
+
51
+ parameters << self.path
52
+ parameters << result.path
53
+
54
+ parameters = parameters.join(" ").squeeze(" ")
55
+
56
+ `lame #{parameters}`
57
+
58
+ rescue Errno::ENOENT
59
+ raise "command 'lame' not found: ensure LAME is installed"
60
+ end
61
+
62
+ unless $?.exitstatus == 0
63
+ raise Attached::Processor::Error, "attachment file must be an audio file"
64
+ end
65
+
66
+ return result
67
+
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,48 @@
1
+ module Attached
2
+ module Processor
3
+ class Base
4
+
5
+
6
+ attr_accessor :file
7
+ attr_accessor :options
8
+ attr_accessor :attachment
9
+
10
+
11
+ # Create and run a processor.
12
+ #
13
+ # Parameters:
14
+ #
15
+ # * file - The file to be processed.
16
+ # * options - The options to be applied to the processing.
17
+ # * attachment - The attachment the processor is being run for.
18
+
19
+ def self.process(file, options = {}, attachment = nil)
20
+ new(file, options, attachment).process
21
+ end
22
+
23
+
24
+ # Create a processor.
25
+ #
26
+ # Parameters:
27
+ #
28
+ # * file - The file to be processed.
29
+ # * options - The options to be applied to the processing.
30
+ # * attachment - The attachment the processor is being run for.
31
+
32
+ def initialize(file, options = {}, attachment = nil)
33
+ @file = file
34
+ @options = options
35
+ @attachment = attachment
36
+ end
37
+
38
+
39
+ # Run the processor.
40
+
41
+ def process
42
+ raise NotImplementedError.new
43
+ end
44
+
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,6 @@
1
+ module Attached
2
+ module Processor
3
+ class Error < StandardError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,92 @@
1
+ require 'attached/processor/base'
2
+ require 'attached/processor/error'
3
+
4
+ module Attached
5
+ module Processor
6
+ class Image < Base
7
+
8
+
9
+ attr_reader :path
10
+ attr_reader :extension
11
+
12
+ attr_reader :width
13
+ attr_reader :height
14
+ attr_reader :operation
15
+
16
+
17
+ # Create a processor.
18
+ #
19
+ # Parameters:
20
+ #
21
+ # * file - The file to be processed.
22
+ # * options - The options to be applied to the processing.
23
+ # * attachment - The attachment the processor is being run for.
24
+
25
+ def initialize(file, options = {}, attachment = nil)
26
+ super
27
+
28
+ @path = self.file.path
29
+
30
+ @size = options[:size]
31
+ @extension = options[:extension]
32
+
33
+ @width, @height, @operation = @size.match(/(\d*)x?(\d*)(.*)/)[1..3] if @size
34
+
35
+ @width ||= options[:width]
36
+ @height ||= options[:height]
37
+ @operation ||= options[:operation]
38
+
39
+ @extension ||= File.extname(self.file.path)
40
+
41
+ @width = Integer(self.width) if self.width
42
+ @height = Integer(self.height) if self.height
43
+ end
44
+
45
+
46
+ # Helper function for calling processors.
47
+ #
48
+ # Usage:
49
+ #
50
+ # self.process
51
+
52
+ def process
53
+
54
+ result = Tempfile.new(["", self.extension])
55
+ result.binmode
56
+
57
+ begin
58
+
59
+ parameters = []
60
+
61
+ parameters << self.path
62
+
63
+ if width and height
64
+ case operation
65
+ when '#' then parameters << "-resize #{width}x#{height}^ -gravity center -extent #{width}x#{height}"
66
+ when '<' then parameters << "-resize #{width}x#{height}\\<"
67
+ when '>' then parameters << "-resize #{width}x#{height}\\>"
68
+ else parameters << "-resize #{width}x#{height}"
69
+ end
70
+ end
71
+
72
+ parameters << result.path
73
+
74
+ parameters = parameters.join(" ").squeeze(" ")
75
+
76
+ `convert #{parameters}`
77
+
78
+ rescue Errno::ENOENT
79
+ raise "command 'convert' not found: ensure ImageMagick is installed"
80
+ end
81
+
82
+ unless $?.exitstatus == 0
83
+ raise Attached::Processor::Error, "attachment file must be an image file"
84
+ end
85
+
86
+ return result
87
+
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -1,23 +1,27 @@
1
+ require 'attached/storage/base'
1
2
  require 'attached/storage/aws'
2
3
 
3
4
  module Attached
4
5
  module Storage
5
6
 
7
+
6
8
  # Create a storage object given a medium and credentials.
7
9
  #
8
10
  # Usage:
9
11
  #
10
- # Attached::Storage.medium()
11
- # Attached::Storage.medium(:aws)
12
+ # Attached::Storage.storage()
13
+ # Attached::Storage.storage(:aws)
14
+ # Attached::Storage.storage(:aws, credentials)
12
15
 
13
16
  def self.storage(medium = :aws, credentials = nil)
14
17
 
15
18
  case medium
16
- when :aws then return Attached::Storage::AWS.new credentials
17
- else raise "Undefined storage medium '#{medium}'."
19
+ when :aws then return Attached::Storage::AWS.new credentials
20
+ else raise "undefined storage medium '#{medium}'"
18
21
  end
19
22
 
20
23
  end
21
24
 
25
+
22
26
  end
23
27
  end
@@ -3,7 +3,7 @@ require 'attached/storage/base'
3
3
  begin
4
4
  require 'aws/s3'
5
5
  rescue LoadError
6
- raise "Installation of 'aws/s3' is required before using 'aws' for storage"
6
+ raise "installation of 'aws/s3' is required before using 'aws' for storage"
7
7
  end
8
8
 
9
9
 
@@ -57,8 +57,8 @@ module Attached
57
57
  connect()
58
58
  begin
59
59
  ::AWS::S3::S3Object.store(path, file, bucket, :access => access)
60
- rescue AWS::S3::NoSuchBucket => e
61
- ::AWS::S3::Bucket.create(bucket)
60
+ rescue ::AWS::S3::NoSuchBucket => e
61
+ ::AWS::S3::Bucket.create(bucket)
62
62
  retry
63
63
  end
64
64
  end
@@ -74,7 +74,7 @@ module Attached
74
74
  connect()
75
75
  begin
76
76
  ::AWS::S3::S3Object.delete(path, bucket)
77
- rescue AWS::S3::NoSuchBucket => e
77
+ rescue ::AWS::S3::NoSuchBucket => e
78
78
  end
79
79
  end
80
80
 
@@ -0,0 +1,6 @@
1
+ module Attached
2
+ module Storage
3
+ class Error < StandardError
4
+ end
5
+ end
6
+ end
@@ -1,3 +1,3 @@
1
1
  module Attached
2
- VERSION = "0.1.8"
2
+ VERSION = "0.1.9"
3
3
  end
@@ -3,10 +3,10 @@ namespace :attached do
3
3
  desc "Process a given 'model' and 'attachment'."
4
4
  task :process, :model, :attachment, :needs => :environment do |t, args|
5
5
 
6
- model = args[:model] or raise "Must specify model."
7
- attachment = args[:attachment] or raise "Must specify attachment."
6
+ model = args[:model] or raise "must specify model"
7
+ attachment = args[:attachment] or raise "must specify attachment"
8
8
 
9
- klass = model.camelize.constantize or raise "Invalid model '#{model}'"
9
+ klass = model.camelize.constantize or raise "invalid model '#{model}'"
10
10
 
11
11
  klass.all.each do |instance|
12
12
  instance.send(attachment).reprocess!
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 8
9
- version: 0.1.8
8
+ - 9
9
+ version: 0.1.9
10
10
  platform: ruby
11
11
  authors:
12
12
  - Kevin Sylvestre
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-12-22 00:00:00 -05:00
17
+ date: 2010-12-23 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -54,11 +54,15 @@ extra_rdoc_files: []
54
54
 
55
55
  files:
56
56
  - lib/attached/attachment.rb
57
- - lib/attached/image.rb
57
+ - lib/attached/processor/audio.rb
58
+ - lib/attached/processor/base.rb
59
+ - lib/attached/processor/error.rb
60
+ - lib/attached/processor/image.rb
58
61
  - lib/attached/processor.rb
59
62
  - lib/attached/railtie.rb
60
63
  - lib/attached/storage/aws.rb
61
64
  - lib/attached/storage/base.rb
65
+ - lib/attached/storage/error.rb
62
66
  - lib/attached/storage.rb
63
67
  - lib/attached/version.rb
64
68
  - lib/attached.rb
@@ -1,88 +0,0 @@
1
- require 'attached/processor'
2
-
3
- module Attached
4
-
5
- class Image < Processor
6
-
7
-
8
- attr_reader :path
9
- attr_reader :extension
10
-
11
- attr_reader :width
12
- attr_reader :height
13
- attr_reader :operation
14
-
15
- # Create a processor.
16
- #
17
- # Parameters:
18
- #
19
- # * file - The file to be processed.
20
- # * options - The options to be applied to the processing.
21
- # * attachment - The attachment the processor is being run for.
22
-
23
- def initialize(file, options = {}, attachment = nil)
24
- super
25
-
26
- @path = self.file.path
27
-
28
- @size = options[:size]
29
- @extension = options[:extension]
30
-
31
- @width, @height, @operation = @size.match(/(\d*)x?(\d*)(.*)/)[1..3] if @size
32
-
33
- @width ||= options[:width]
34
- @height ||= options[:height]
35
- @operation ||= options[:operation]
36
-
37
- @extension ||= File.extname(self.file.path)
38
-
39
- @width = Integer(self.width)
40
- @height = Integer(self.height)
41
-
42
- raise "Image processor requires specification of 'width' or 'size'" unless self.width
43
- raise "Image processor requires specification of 'height' or 'size'" unless self.height
44
- end
45
-
46
-
47
- # Helper function for calling processors.
48
- #
49
- # Usage:
50
- #
51
- # self.process
52
-
53
- def process
54
- result = Tempfile.new(["", self.extension])
55
- result.binmode
56
-
57
- begin
58
- parameters = []
59
-
60
- parameters << self.path
61
-
62
- case operation
63
- when '#' then parameters << "-resize #{width}x#{height}^ -gravity center -extent #{width}x#{height}"
64
- when '<' then parameters << "-resize #{width}x#{height}\\<"
65
- when '>' then parameters << "-resize #{width}x#{height}\\>"
66
- else parameters << "-resize #{width}x#{height}"
67
- end
68
-
69
- parameters << result.path
70
-
71
- parameters = parameters.join(" ").squeeze(" ")
72
-
73
- `convert #{parameters}`
74
-
75
- raise "Command 'convert' failed. Ensure upload file is an image and options are correct." unless $?.exitstatus == 0
76
-
77
- rescue Errno::ENOENT
78
-
79
- raise "Command 'convert' not found. Ensure 'Image Magick' is installed."
80
-
81
- end
82
-
83
- return result
84
- end
85
-
86
-
87
- end
88
- end