attached 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
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