From d4ec32f81dbbda625ef56a9fa41ba836c1099e45 Mon Sep 17 00:00:00 2001 From: Ishu Date: Fri, 6 Jan 2012 18:03:23 +0530 Subject: [PATCH 1/8] Added support for uploading blob to attach module. --- lib/hapgood/attach.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/hapgood/attach.rb b/lib/hapgood/attach.rb index a0fc222..5001f6c 100644 --- a/lib/hapgood/attach.rb +++ b/lib/hapgood/attach.rb @@ -1,4 +1,5 @@ require 'hapgood/attach/sources' +require 'base64' module Hapgood # :nodoc: module Attach # :nodoc: @@ -122,6 +123,16 @@ def url=(u) end end + def blob=(bl) + return unless bl + destroy_source # Discard any existing source + begin + self.source = Sources::Blob.new(Base64.decode64(bl), blob_metadata) + rescue => e # Can't do much here -we have to wait until the validation phase to resurrect/reconstitute errors + logger.error("Attach: *********ERROR: can't load blob data (#{e})") + end + end + # Get the source. Rescue exceptions and make them errors on the source virtual attribute. def source @source ||= uri && Sources::Base.reload(uri, stored_metadata) @@ -232,6 +243,13 @@ def cgi_metadata(data) end end + def blob_metadata + Hash.new.tap do |md| + md[:filename] = filename + md[:mime_type] = ::Mime::Type.lookup(mime_type) + end + end + # Extract stored metadata from attributes to enrichen a purely binary source to the same level as a CGI-supplied source. def stored_metadata %w(filename mime_type).inject(Hash.new) {|hash, key| hash[key.to_sym] = self.send(key.to_sym);hash} From 55c57aaa7efed144d860e37e188ede79094832f6 Mon Sep 17 00:00:00 2001 From: Ishu Date: Wed, 25 Jan 2012 19:24:59 +0530 Subject: [PATCH 2/8] Added support for getting aspect of a single frame of a multiframe file. --- lib/hapgood/attach/sources/base.rb | 5 +++++ lib/hapgood/attach/sources/rmagick.rb | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/lib/hapgood/attach/sources/base.rb b/lib/hapgood/attach/sources/base.rb index 46632f3..69d2156 100644 --- a/lib/hapgood/attach/sources/base.rb +++ b/lib/hapgood/attach/sources/base.rb @@ -104,6 +104,11 @@ def change_image(&block) is.change_image(&block) end + def change_frame(i, &block) + is = self.is_a?(Sources::Rmagick) ? self : Sources::Rmagick.new(self) + is.change_frame(i, &block) + end + def valid? error.nil? end diff --git a/lib/hapgood/attach/sources/rmagick.rb b/lib/hapgood/attach/sources/rmagick.rb index 7113166..fe16358 100644 --- a/lib/hapgood/attach/sources/rmagick.rb +++ b/lib/hapgood/attach/sources/rmagick.rb @@ -114,6 +114,28 @@ def change_image(&block) self end + # Method to get a particular frame. + def frame_image(fi) + @image ||= begin + format = self.class.format_for_mime_type(@source.mime_type) + read_spec = "#{@source.tempfile.path}[#{fi}]" + read_spec = "#{format}:" + read_spec if format + ::Magick::Image.read(read_spec).first + end + end + + # Method to yield a particular frame. + # TODO: These methods should typically merge away with change_image methods above. + def change_frame(fi, &block) + yield frame_image(fi) + # TODO: Typical attach module dependencies. Always take care of these globals. + @tempfile = nil + @uri = nil # Once transformed, all external sources are invalid. + @blob = nil # Once transformed, we need to reset the data. Now the getter can lazily load the blob. + @persistent = false + self + end + private # Extract useful information from (ExiF | IPTC) header, if possible. def exif_data From 39ca15737fa75392405a66941da4961148c6ae2b Mon Sep 17 00:00:00 2001 From: Ishu Date: Wed, 25 Jan 2012 23:21:28 +0530 Subject: [PATCH 3/8] Added methods to get the frame count of the source. --- lib/hapgood/attach/sources/base.rb | 6 ++++++ lib/hapgood/attach/sources/rmagick.rb | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/lib/hapgood/attach/sources/base.rb b/lib/hapgood/attach/sources/base.rb index 69d2156..27d4f23 100644 --- a/lib/hapgood/attach/sources/base.rb +++ b/lib/hapgood/attach/sources/base.rb @@ -109,6 +109,12 @@ def change_frame(i, &block) is.change_frame(i, &block) end + def frame_count + raise "Unable to process source" unless processable? + is = self.is_a?(Sources::Rmagick) ? self : Sources::Rmagick.new(self) + is.frame_count + end + def valid? error.nil? end diff --git a/lib/hapgood/attach/sources/rmagick.rb b/lib/hapgood/attach/sources/rmagick.rb index fe16358..e929af0 100644 --- a/lib/hapgood/attach/sources/rmagick.rb +++ b/lib/hapgood/attach/sources/rmagick.rb @@ -136,6 +136,10 @@ def change_frame(fi, &block) self end + def frame_count + ::Magick::Image.read(@source.tempfile.path).length + end + private # Extract useful information from (ExiF | IPTC) header, if possible. def exif_data From a2a72ba95ff090c2f618d74b2e9084e229bf3479 Mon Sep 17 00:00:00 2001 From: Ishu Date: Thu, 16 Feb 2012 18:01:54 +0530 Subject: [PATCH 4/8] Discard the blank urls !! --- lib/hapgood/attach.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/hapgood/attach.rb b/lib/hapgood/attach.rb index 5001f6c..0de6edb 100644 --- a/lib/hapgood/attach.rb +++ b/lib/hapgood/attach.rb @@ -114,7 +114,7 @@ def url # Setter for virtual url attribute used to reference external data sources. def url=(u) @url = u - return unless u + return unless u && !u.blank? destroy_source # Discard any existing source begin self.source = Sources::Base.load(::URI.parse(u)) From 6b6a388e9f917f8adbd7682b20e4de9be85bc08a Mon Sep 17 00:00:00 2001 From: Ishu Date: Wed, 21 Mar 2012 15:59:37 +0530 Subject: [PATCH 5/8] Get the attributes of a blob in a single hash !! --- lib/hapgood/attach.rb | 8 ++++---- lib/hapgood/attach/sources/blob.rb | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/hapgood/attach.rb b/lib/hapgood/attach.rb index 0de6edb..af53f4c 100644 --- a/lib/hapgood/attach.rb +++ b/lib/hapgood/attach.rb @@ -127,7 +127,7 @@ def blob=(bl) return unless bl destroy_source # Discard any existing source begin - self.source = Sources::Blob.new(Base64.decode64(bl), blob_metadata) + self.source = Sources::Base.load(Base64.decode64(bl[:data]), blob_metadata(bl)) rescue => e # Can't do much here -we have to wait until the validation phase to resurrect/reconstitute errors logger.error("Attach: *********ERROR: can't load blob data (#{e})") end @@ -243,10 +243,10 @@ def cgi_metadata(data) end end - def blob_metadata + def blob_metadata(b) Hash.new.tap do |md| - md[:filename] = filename - md[:mime_type] = ::Mime::Type.lookup(mime_type) + md[:filename] = b[:filename] + md[:mime_type] = ::Mime::Type.lookup(b[:content_type]) end end diff --git a/lib/hapgood/attach/sources/blob.rb b/lib/hapgood/attach/sources/blob.rb index 52a1554..cb1bf3a 100644 --- a/lib/hapgood/attach/sources/blob.rb +++ b/lib/hapgood/attach/sources/blob.rb @@ -5,6 +5,10 @@ module Attach # :nodoc: module Sources # Methods for blob sources class Blob < Hapgood::Attach::Sources::Base + def self.load(d, m={}) + new(d, m) + end + # Does this source persist at the URI independent of this application? def persistent? false From 8b0ba8975ec277897c9e254fbe6d1fc89445b279 Mon Sep 17 00:00:00 2001 From: Ishwinder Date: Thu, 17 Sep 2015 19:12:33 +0530 Subject: [PATCH 6/8] Building Gemspec --- enbake_attach.gemspec | 17 +++++++++++++++++ init.rb | 4 ---- 2 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 enbake_attach.gemspec diff --git a/enbake_attach.gemspec b/enbake_attach.gemspec new file mode 100644 index 0000000..76786a5 --- /dev/null +++ b/enbake_attach.gemspec @@ -0,0 +1,17 @@ +Gem::Specification.new do |s| + s.name = 'Enbake Attach' + s.version = '0.0.1' + s.date = '2015-09-17' + s.summary = "Hola!" + s.description = "A simple hello world gem" + s.authors = ["Ishwinder Singh"] + s.email = 'singh.ishwinder@gmail.com' + s.files = ["lib/hapgood/attach.rb"] + + s.add_dependency('exifr') + s.add_dependency('rmagick') + + s.homepage = + 'http://github.com/ishwinder/enbake_attach' + s.license = 'MIT' +end \ No newline at end of file diff --git a/init.rb b/init.rb index a6182a5..f59e031 100644 --- a/init.rb +++ b/init.rb @@ -1,9 +1,5 @@ # Due to the sequence of dependency processing and plugin initialization, these statements cannot be used to auto-install # missing gems -they are here solely for documentation. -config.gem 'exifr', :version => '>=1.0.3' -config.gem 'rmagick', :version => '>=2.7.2', :lib => 'RMagick' -config.gem 'aws-s3', :version => '>=0.6.2', :lib => 'aws/s3' - require 'geometry' require 'hapgood/attach' From e5d1d33939608323b9164ee1b7e0aa3e245968ef Mon Sep 17 00:00:00 2001 From: Ishwinder Date: Thu, 17 Sep 2015 21:06:35 +0530 Subject: [PATCH 7/8] Some changes to gem --- enbake_attach.gemspec | 9 +++++---- lib/enbake_attach.rb | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 lib/enbake_attach.rb diff --git a/enbake_attach.gemspec b/enbake_attach.gemspec index 76786a5..c6e31d3 100644 --- a/enbake_attach.gemspec +++ b/enbake_attach.gemspec @@ -1,12 +1,13 @@ Gem::Specification.new do |s| - s.name = 'Enbake Attach' + s.name = 'enbake_attach' s.version = '0.0.1' s.date = '2015-09-17' - s.summary = "Hola!" - s.description = "A simple hello world gem" + s.summary = "Enbake Attach" + s.description = "Enbake Attach is a Gem for handling attachments in Rails. Its a whoopie doo version of attachment_fu" s.authors = ["Ishwinder Singh"] s.email = 'singh.ishwinder@gmail.com' - s.files = ["lib/hapgood/attach.rb"] + s.files = `git ls-files`.split($/) + s.require_paths = ["lib"] s.add_dependency('exifr') s.add_dependency('rmagick') diff --git a/lib/enbake_attach.rb b/lib/enbake_attach.rb new file mode 100644 index 0000000..14f05c5 --- /dev/null +++ b/lib/enbake_attach.rb @@ -0,0 +1,2 @@ +require 'geometry' +require 'hapgood/attach' \ No newline at end of file From 61b51e978d0b656a8bfe0884ce171f01f90fc063 Mon Sep 17 00:00:00 2001 From: Ishwinder Date: Thu, 17 Sep 2015 22:29:31 +0530 Subject: [PATCH 8/8] 4.2 compatibility fixes. --- lib/hapgood/attach.rb | 2 +- lib/hapgood/attach/sources/base.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/hapgood/attach.rb b/lib/hapgood/attach.rb index af53f4c..01cedf2 100644 --- a/lib/hapgood/attach.rb +++ b/lib/hapgood/attach.rb @@ -36,7 +36,7 @@ def has_attachment(options = {}) options[:store] ||= Proc.new {|i, e| "file://localhost#{::File.join(RAILS_ROOT, 'public', 'attachments', [i,e].compact.join('.'))}"} # doing these shenanigans so that #attachment_options is available to processors and backends - class_inheritable_accessor :attachment_options + class_attribute :attachment_options self.attachment_options = options # only need to define these once on a class diff --git a/lib/hapgood/attach/sources/base.rb b/lib/hapgood/attach/sources/base.rb index 27d4f23..8e50343 100644 --- a/lib/hapgood/attach/sources/base.rb +++ b/lib/hapgood/attach/sources/base.rb @@ -14,8 +14,8 @@ module Sources # data : A blob (string) of the attachment's data # tempfile : A tempfile of the attachment class Base - class_inheritable_accessor :tempfile_path, :instance_writer => false - write_inheritable_attribute(:tempfile_path, File.join(RAILS_ROOT, 'tmp', 'attach')) + class_attribute :tempfile_path + self.tempfile_path = File.join(RAILS_ROOT, 'tmp', 'attach') attr_reader :error, :data