-
-
Save janv/224261 to your computer and use it in GitHub Desktop.
Small tips for building a polymorphic usage of Paperclip, with video to flv, video thumbnail, mp3 tag extraction, zip file listing processors.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class AddAttachmentsDataToWrapper < ActiveRecord::Migration | |
def self.up | |
add_column :wrappers, :data_file_name, :string | |
add_column :wrappers, :data_content_type, :string | |
add_column :wrappers, :data_file_size, :integer | |
add_column :wrappers, :data_updated_at, :datetime | |
end | |
def self.down | |
remove_column :wrappers, :data_file_name | |
remove_column :wrappers, :data_content_type | |
remove_column :wrappers, :data_file_size | |
remove_column :wrappers, :data_updated_at | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Paperclip | |
class AudioTag < Processor | |
def initialize file, options = {}, attachment = nil | |
super | |
@file = file | |
@data = attachment | |
end | |
def make | |
begin | |
src = @file | |
src.close | |
mp3 = Mp3Info.open(File.expand_path(src.path)) | |
@data.instance.info = mp3.tag.to_a.inject("#{@data.instance.info}\n---\n"){|result, element| | |
result + "*#{element.first}* : #{element.last}\n".titleize} | |
rescue PaperclipCommandLineError | |
raise PaperclipError, "There was an error processing the tag extraction for #{@basename}" if @whiny | |
end | |
nil | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CreateWrappers < ActiveRecord::Migration | |
def self.up | |
create_table :wrappers do |t| | |
t.string :name | |
t.references :user | |
t.references :attachable, :polymorphic => true | |
t.boolean :private, :default => false | |
t.text :info | |
t.text :doc_type | |
t.timestamps | |
end | |
add_index :wrappers, :user_id | |
add_index :wrappers, :attachable_type | |
add_index :wrappers, :attachable_id | |
end | |
def self.down | |
drop_table :wrappers | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Paperclip | |
class Empty < Processor | |
def initialize file, options = {}, attachment = nil | |
end | |
def make | |
nil | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Paperclip.interpolates :zfull_path do |d,s| | |
att = d.instance.attachable_type || "_no_type" | |
prn = d.instance.proc_name | |
ext = d.instance.data_file_name.scan(/.*\.([^.]*?)$/).to_s | |
if (s == :original) or | |
(prn == 'image') or | |
((prn == 'video') and (s == :thumb)) or | |
((prn == 'pdf') and (s != :small)) then | |
"wrappers/#{att}/:style/:basename.:id.:extension" | |
elsif (prn == 'video' and s == :large) | |
"wrappers/#{att}/#{s}/:basename.:id.flv" | |
else | |
"images/styles/#{ext}.:style.png" | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Paperclip | |
# Handles thumbnailing images that are uploaded. | |
class Pdf < Processor | |
attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options | |
# Creates a Thumbnail object set to work on the +file+ given. It | |
# will attempt to transform the image into one defined by +target_geometry+ | |
# which is a "WxH"-style string. +format+ will be inferred from the +file+ | |
# unless specified. Thumbnail creation will raise no errors unless | |
# +whiny+ is true (which it is, by default. If +convert_options+ is | |
# set, the options will be appended to the convert command upon image conversion | |
def initialize file, options = {}, attachment = nil | |
super | |
geometry = options[:geometry] | |
@file = file | |
@crop = geometry[-1,1] == '#' | |
@target_geometry = Geometry.parse geometry | |
@current_geometry = Geometry.from_file @file | |
@convert_options = options[:convert_options] | |
@whiny = options[:whiny].nil? ? true : options[:whiny] | |
@format = options[:format] | |
@current_format = File.extname(@file.path) | |
@basename = File.basename(@file.path, @current_format) | |
end | |
# Returns true if the +target_geometry+ is meant to crop. | |
def crop? | |
@crop | |
end | |
# Returns true if the image is meant to make use of additional convert options. | |
def convert_options? | |
not @convert_options.blank? | |
end | |
# Performs the conversion of the +file+ into a thumbnail. Returns the Tempfile | |
# that contains the new image. | |
def make | |
src = @file | |
dst = Tempfile.new([@basename, @format].compact.join(".")) | |
dst.binmode | |
################## added -density 196 *before* the file call for better rendering | |
command = <<-end_command | |
-density 196 | |
"#{ File.expand_path(src.path) }[0]" | |
#{ transformation_command } | |
"#{ File.expand_path(dst.path) }" | |
end_command | |
begin | |
success = Paperclip.run("convert", command.gsub(/\s+/, " ")) | |
rescue PaperclipCommandLineError | |
raise PaperclipError, "There was an error processing the thumbnail for #{@basename}" if @whiny | |
end | |
dst | |
end | |
# Returns the command ImageMagick's +convert+ needs to transform the image | |
# into the thumbnail. | |
def transformation_command | |
scale, crop = @current_geometry.transformation_to(@target_geometry, crop?) | |
trans = "-resize \"#{scale}\"" | |
trans << " -crop \"#{crop}\" +repage" if crop | |
trans << " #{convert_options}" if convert_options? | |
trans | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
lst = ["zip", "txt", "doc", "ppt", "mp3", "jpg", "xls", "xlsx", "docx", "flv", "wmv", "avi", "pdf"] | |
id = 1 | |
ty = 'testing' | |
lst.each do |fic| | |
w = Wrapper.new | |
w.id = id | |
w.attachable_type = ty | |
File.open("test.#{fic}",'rb'){|f| w.data = f} | |
puts "test.#{fic} --> #{w.proc_name} -- #{w.data.content_type}" | |
puts "-------" | |
puts w.info | |
[:original,:small,:thumb,:large].each{|s| puts w.data.path(s)} | |
puts "------------------------------------" | |
w.save | |
id+=1 | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Paperclip | |
class VideoConvert < Processor | |
attr_accessor :whiny, :tt, :file, :basename | |
def initialize(file, options = {}, attachment = nil) | |
super | |
@file = file | |
@whiny = options[:whiny].nil? ? true : options[:whiny] | |
@basename = File.basename(file.path, File.extname(file.path)) | |
@data = attachment | |
end | |
def make | |
src = @file | |
flv = Tempfile.new([ @basename, 'flv' ].compact.join(".")) | |
flv.close | |
command = <<-end_command | |
-i #{File.expand_path(src.path)} -ar 22050 -ab 32 -acodec libmp3lame | |
-s 480x360 -vcodec flv -r 25 -qscale 8 -f flv -y #{File.expand_path(flv.path)} | |
end_command | |
command.gsub!(/\s+/, " ") | |
@tt = command | |
begin | |
success = Paperclip.run('ffmpeg', command) | |
rescue PaperclipCommandLineError | |
raise PaperclipError, "There was an error processing the video convert for #{@basename}" if whiny | |
end | |
flv | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Paperclip | |
class VideoThumb < Processor | |
attr_accessor :time_offset, :geometry, :whiny | |
def initialize(file, options = {}, attachment = nil) | |
super | |
@data = attachment | |
@time_offset = options[:time_offset] || '-4' | |
unless options[:geometry].nil? || (@geometry = Geometry.parse(options[:geometry])).nil? | |
@geometry.width = (@geometry.width / 2.0).floor * 2.0 | |
@geometry.height = (@geometry.height / 2.0).floor * 2.0 | |
@geometry.modifier = '' | |
end | |
@whiny = options[:whiny].nil? ? true : options[:whiny] | |
@basename = File.basename(file.path, File.extname(file.path)) | |
end | |
def make | |
dst = Tempfile.new([ @basename, 'jpg' ].compact.join(".")) | |
dst.binmode | |
cmd = %Q[-itsoffset #{time_offset} -i "#{File.expand_path(file.path)}" -y -vcodec mjpeg -vframes 1 -an -f rawvideo ] | |
cmd << "-s #{geometry.to_s} " unless geometry.nil? | |
cmd << %Q["#{File.expand_path(dst.path)}"] | |
begin | |
success = Paperclip.run('ffmpeg', cmd) | |
rescue PaperclipCommandLineError | |
raise PaperclipError, "There was an error processing the thumbnail for #{@basename}" if whiny | |
end | |
dst | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Wrapper < ActiveRecord::Base | |
TypesWrapper = [ 'application/x-docx', | |
'application/x-doc', 'application/x-rtf', | |
'application/x-pps', 'application/x-ppt', 'application/x-pptx', | |
'application/x-xls', 'application/x-xlsx','application/x-csv', | |
'application/x-msg', | |
'application/x-zip', | |
'text/plain', | |
'application/x-pdf','application/pdf', | |
'application/mp3', 'application/x-mp3', 'audio/mpeg', 'audio/mp3', | |
'image/gif', 'image/png', 'image/x-png', 'image/jpeg', 'image/jpg', | |
'video/mpeg', 'application/x-flv', 'video/quicktime' ,'application/x-wmv', | |
'application/x-avi'] | |
acts_as_commentable | |
acts_as_textiled :name, :info | |
belongs_to :user | |
has_attached_file :data, | |
:url => "/:zfull_path", | |
:path => ":rails_root/public/:zfull_path", | |
:whiny => true | |
attr_protected :data_file_name, :data_content_type, :data_size | |
before_post_process :validate_processor | |
validates_attachment_size :data, :less_than => 10.megabytes | |
validates_attachment_content_type :data, :content_type => TypesWrapper | |
def proc_name | |
type, detail = data.content_type.scan(/^(video|audio|application|text|image)\/(.*?)$/).flatten | |
case type | |
when 'image' then 'image' | |
when 'video','audio' then type | |
when 'text' then 'text' | |
when 'application' | |
case detail | |
when /pdf$/ then 'pdf' | |
when /mp3$/ then 'audio' | |
when /mov|flv|wmv|avi$/ then 'video' | |
when /csv|xls.?$/ then 'excel' | |
when /doc.?|txt|rtf$/ then 'word' | |
when /pp..?/ then 'powerpoint' | |
when 'msg' then 'message' | |
when /^(?:x-)?zip$/ then 'zip' | |
else 'document' | |
end | |
end | |
end | |
def validate_processor | |
case proc_name | |
when "image" then | |
data.styles[:small] = { :geometry => "64x64>", :format => "png", :processors => "thumbnail" } | |
data.styles[:thumb] = { :geometry => "128x128#", :format => "png", :processors => "thumbnail" } | |
data.styles[:large] = { :geometry => "300x400#", :format => "png", :processors => "thumbnail" } | |
when "document",'excel','word','powerpoint','text' | |
data.styles[:small] = { :geometry => "64x64>", :format => "png", :processors => "empty" } | |
data.styles[:thumb] = { :geometry => "128x128#", :format => "png", :processors => "empty" } | |
data.styles[:large] = { :geometry => "300x400#", :format => "png", :processors => "empty" } | |
when "zip" | |
data.styles[:small] = { :geometry => "64x64>", :format => "png", :processors => "empty" } | |
data.styles[:thumb] = { :geometry => "128x128#", :format => "png", :processors => "empty" } | |
data.styles[:large] = { :geometry => "300x400#", :format => "png", :processors => "zip_info" } | |
when "video" | |
data.styles[:small] = { :geometry => "64x64>", :format => "png", :processors => "empty" } | |
data.styles[:thumb] = { :geometry => "128x128#", :format => "png", :processors => "video_thumb" } | |
data.styles[:large] = { :geometry => "300x400#", :format => "flv", :processors => "video_convert"} | |
when "audio" | |
data.styles[:small] = { :geometry => "64x64>", :format => "png", :processors => "audio_tag" } | |
data.styles[:thumb] = { :geometry => "128x128#", :format => "png", :processors => "empty" } | |
data.styles[:large] = { :geometry => "300x400#", :format => "png", :processors => "empty" } | |
when "pdf" | |
data.styles[:small] = { :geometry => "64x64>", :format => "png", :processors => "empty" } | |
data.styles[:thumb] = { :geometry => "128x128#", :format => "png", :processors => "pdf" } | |
data.styles[:large] = { :geometry => "300x400#", :format => "png", :processors => "pdf" } | |
end | |
true | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment