Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
technoweenie committed Mar 6, 2008
2 parents 8ef3196 + aeb9ecf commit e1705ef
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 88 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
test/amazon_s3.yml
test/debug.log
192 changes: 112 additions & 80 deletions lib/technoweenie/attachment_fu.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,60 +45,57 @@ def has_attachment(options = {})
options[:thumbnail_class] ||= self
options[:s3_access] ||= :public_read
options[:content_type] = [options[:content_type]].flatten.collect! { |t| t == :image ? Technoweenie::AttachmentFu.content_types : t }.flatten unless options[:content_type].nil?

unless options[:thumbnails].is_a?(Hash)
raise ArgumentError, ":thumbnails option should be a hash: e.g. :thumbnails => { :foo => '50x50' }"
end


extend ClassMethods unless (class << self; included_modules; end).include?(ClassMethods)
include InstanceMethods unless included_modules.include?(InstanceMethods)

parent_options = attachment_options || {}
# doing these shenanigans so that #attachment_options is available to processors and backends
class_inheritable_accessor :attachment_options
self.attachment_options = options

# only need to define these once on a class
unless included_modules.include?(InstanceMethods)
attr_accessor :thumbnail_resize_options
attr_accessor :thumbnail_resize_options

attachment_options[:storage] ||= (attachment_options[:file_system_path] || attachment_options[:path_prefix]) ? :file_system : :db_file
attachment_options[:storage] ||= parent_options[:storage]
attachment_options[:path_prefix] ||= attachment_options[:file_system_path]
if attachment_options[:path_prefix].nil?
attachment_options[:path_prefix] = attachment_options[:storage] == :s3 ? table_name : File.join("public", table_name)
end
attachment_options[:path_prefix] = attachment_options[:path_prefix][1..-1] if options[:path_prefix].first == '/'

with_options :foreign_key => 'parent_id' do |m|
m.has_many :thumbnails, :class_name => attachment_options[:thumbnail_class].to_s
m.belongs_to :parent, :class_name => base_class.to_s
end

attachment_options[:storage] ||= (attachment_options[:file_system_path] || attachment_options[:path_prefix]) ? :file_system : :db_file
attachment_options[:path_prefix] ||= attachment_options[:file_system_path]
if attachment_options[:path_prefix].nil?
attachment_options[:path_prefix] = attachment_options[:storage] == :s3 ? table_name : File.join("public", table_name)
storage_mod = Technoweenie::AttachmentFu::Backends.const_get("#{options[:storage].to_s.classify}Backend")
include storage_mod unless included_modules.include?(storage_mod)

case attachment_options[:processor]
when :none, nil
processors = Technoweenie::AttachmentFu.default_processors.dup
begin
if processors.any?
attachment_options[:processor] = "#{processors.first}Processor"
processor_mod = Technoweenie::AttachmentFu::Processors.const_get(attachment_options[:processor])
include processor_mod unless included_modules.include?(processor_mod)
end
rescue LoadError, MissingSourceFile
processors.shift
retry
end
attachment_options[:path_prefix] = attachment_options[:path_prefix][1..-1] if options[:path_prefix].first == '/'

with_options :foreign_key => 'parent_id' do |m|
m.has_many :thumbnails, :class_name => attachment_options[:thumbnail_class].to_s
m.belongs_to :parent, :class_name => base_class.to_s
end unless options[:thumbnails].empty?
before_destroy :destroy_thumbnails

before_validation :set_size_from_temp_path
after_save :after_process_attachment
after_destroy :destroy_file
extend ClassMethods
include InstanceMethods
include Technoweenie::AttachmentFu::Backends.const_get("#{options[:storage].to_s.classify}Backend")
case attachment_options[:processor]
when :none
when nil
processors = Technoweenie::AttachmentFu.default_processors.dup
begin
if processors.any?
attachment_options[:processor] = "#{processors.first}Processor"
include Technoweenie::AttachmentFu::Processors.const_get(attachment_options[:processor])
end
rescue LoadError, MissingSourceFile
processors.shift
retry
end
else
begin
include Technoweenie::AttachmentFu::Processors.const_get("#{options[:processor].to_s.classify}Processor")
rescue LoadError, MissingSourceFile
puts "Problems loading #{options[:processor]}Processor: #{$!}"
end
else
begin
processor_mod = Technoweenie::AttachmentFu::Processors.const_get("#{attachment_options[:processor].to_s.classify}Processor")
include processor_mod unless included_modules.include?(processor_mod)
rescue LoadError, MissingSourceFile
puts "Problems loading #{options[:processor]}Processor: #{$!}"
end
after_validation :process_attachment
end
end unless parent_options[:processor] # Don't let child override processor
end
end

Expand All @@ -116,41 +113,55 @@ def image?(content_type)
content_types.include?(content_type)
end

# Callback after an image has been resized.
#
# class Foo < ActiveRecord::Base
# acts_as_attachment
# after_resize do |record, img|
# record.aspect_ratio = img.columns.to_f / img.rows.to_f
# end
# end
def after_resize(&block)
write_inheritable_array(:after_resize, [block])
def self.extended(base)
base.class_inheritable_accessor :attachment_options
base.before_destroy :destroy_thumbnails
base.before_validation :set_size_from_temp_path
base.after_save :after_process_attachment
base.after_destroy :destroy_file
base.after_validation :process_attachment
if defined?(::ActiveSupport::Callbacks)
base.define_callbacks :after_resize, :after_attachment_saved, :before_thumbnail_saved
end
end

# Callback after an attachment has been saved either to the file system or the DB.
# Only called if the file has been changed, not necessarily if the record is updated.
#
# class Foo < ActiveRecord::Base
# acts_as_attachment
# after_attachment_saved do |record|
# ...
# end
# end
def after_attachment_saved(&block)
write_inheritable_array(:after_attachment_saved, [block])
end
unless defined?(::ActiveSupport::Callbacks)
# Callback after an image has been resized.
#
# class Foo < ActiveRecord::Base
# acts_as_attachment
# after_resize do |record, img|
# record.aspect_ratio = img.columns.to_f / img.rows.to_f
# end
# end
def after_resize(&block)
write_inheritable_array(:after_resize, [block])
end

# Callback before a thumbnail is saved. Use this to pass any necessary extra attributes that may be required.
#
# class Foo < ActiveRecord::Base
# acts_as_attachment
# before_thumbnail_saved do |record, thumbnail|
# ...
# end
# end
def before_thumbnail_saved(&block)
write_inheritable_array(:before_thumbnail_saved, [block])
# Callback after an attachment has been saved either to the file system or the DB.
# Only called if the file has been changed, not necessarily if the record is updated.
#
# class Foo < ActiveRecord::Base
# acts_as_attachment
# after_attachment_saved do |record|
# ...
# end
# end
def after_attachment_saved(&block)
write_inheritable_array(:after_attachment_saved, [block])
end

# Callback before a thumbnail is saved. Use this to pass any necessary extra attributes that may be required.
#
# class Foo < ActiveRecord::Base
# acts_as_attachment
# before_thumbnail_saved do |record, thumbnail|
# ...
# end
# end
def before_thumbnail_saved(&block)
write_inheritable_array(:before_thumbnail_saved, [block])
end
end

# Get the thumbnail class, which is the current attachment class by default.
Expand Down Expand Up @@ -278,7 +289,8 @@ def temp_path

# Gets an array of the currently used temp paths. Defaults to a copy of #full_filename.
def temp_paths
@temp_paths ||= (new_record? || !File.exist?(full_filename)) ? [] : [copy_to_temp_file(full_filename)]
@temp_paths ||= (new_record? || !respond_to?(:full_filename) || !File.exist?(full_filename) ?
[] : [copy_to_temp_file(full_filename)])
end

# Adds a new temp_path to the array. This should take a string or a Tempfile. This class makes no
Expand Down Expand Up @@ -397,10 +409,30 @@ def callback_with_args(method, arg = self)
result = callback.call(self, arg)
return false if result == false
end
result
end

return result
# Rather ugly monkey-patch of AS::Callbacks to support taking an arg
if defined?(::ActiveSupport::Callbacks)
def callbacks_for(method) #:nodoc: compatibility method
self.class.send("#{method}_callback_chain")
end
class ::ActiveSupport::Callbacks::Callback
# Make callbacks accept arguments, but only pass them along to procs for now
def call(object, *args)
if should_run_callback?(object)
case method
when Proc
args = [object, *args].compact
method.call(*args)
else
evaluate_method(method, object)
end
end
end
end
end

# Removes the thumbnails for the attachment, if it has any
def destroy_thumbnails
self.thumbnails.each { |thumbnail| thumbnail.destroy } if thumbnailable?
Expand Down
6 changes: 0 additions & 6 deletions test/amazon_s3.yml

This file was deleted.

2 changes: 1 addition & 1 deletion test/fixtures/attachment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,6 @@ class S3WithPathPrefixAttachment < S3Attachment
has_attachment :storage => :s3, :path_prefix => 'some/custom/path/prefix', :processor => :rmagick
validates_as_attachment
end
rescue Technoweenie::AttachmentFu::Backends::S3Backend::ConfigFileNotFoundError
rescue
puts "S3 error: #{$!}"
end
3 changes: 2 additions & 1 deletion test/test_helper.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
$:.unshift(File.dirname(__FILE__) + '/../lib')

ENV['RAILS_ENV'] = 'test'
ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '../../../..'

require 'test/unit'
require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb'))
require File.expand_path(File.join(ENV['RAILS_ROOT'], 'config/environment.rb'))
require 'active_record/fixtures'
require 'action_controller/test_process'

Expand Down

0 comments on commit e1705ef

Please sign in to comment.