lib/joint.rb in joint-0.1.1 vs lib/joint.rb in joint-0.2
- old
+ new
@@ -1,70 +1,84 @@
+require 'set'
require 'mime/types'
require 'wand'
module Joint
autoload :Version, 'joint/version'
- def self.file_name(file)
- file.respond_to?(:original_filename) ? file.original_filename : File.basename(file.path)
- end
-
module ClassMethods
def attachment(name)
- self.class.class_inheritable_accessor :attachment_names
+ self.class.class_inheritable_accessor :attachment_names unless self.class.respond_to?(:attachment_names)
self.class.attachment_names ||= []
self.class.attachment_names << name
after_save :save_attachments
- before_destroy :destroy_attached_files
+ after_save :destroy_nil_attachments
+ before_destroy :destroy_all_attachments
key "#{name}_id".to_sym, ObjectId
key "#{name}_name".to_sym, String
key "#{name}_size".to_sym, Integer
key "#{name}_type".to_sym, String
- define_method(name) do
- AttachmentProxy.new(self, name)
- end
+ class_eval <<-EOC
+ def #{name}
+ @#{name} ||= AttachmentProxy.new(self, :#{name})
+ end
- define_method("#{name}=") do |file|
- self["#{name}_id"] = Mongo::ObjectID.new
- self["#{name}_size"] = File.size(file)
- self["#{name}_type"] = Wand.wave(file.path)
- self["#{name}_name"] = Joint.file_name(file)
- attachment_assignments[name] = file
- end
+ def #{name}?
+ self.send(:#{name}_id?)
+ end
+
+ def #{name}=(file)
+ if file.nil?
+ nil_attachments << :#{name}
+ else
+ self["#{name}_id"] = Mongo::ObjectID.new
+ self["#{name}_size"] = File.size(file)
+ self["#{name}_type"] = Wand.wave(file.path)
+ self["#{name}_name"] = Joint.file_name(file)
+ assigned_attachments[:#{name}] = file
+ end
+ end
+ EOC
end
end
module InstanceMethods
- def attachment_assignments
- @attachment_assignments ||= {}
- end
-
def grid
@grid ||= Mongo::Grid.new(database)
end
private
+ def assigned_attachments
+ @assigned_attachments ||= {}
+ end
+
+ def nil_attachments
+ @nil_attachments ||= Set.new
+ end
+
def save_attachments
- attachment_assignments.each do |attachment|
+ assigned_attachments.each do |attachment|
name, file = attachment
- content_type = self["#{name}_type"]
-
if file.respond_to?(:read)
- grid.put(file.read, self["#{name}_name"], :content_type => content_type, :_id => self["#{name}_id"])
+ file.rewind if file.respond_to?(:rewind)
+ grid.put(file.read, self["#{name}_name"], {
+ :_id => self["#{name}_id"],
+ :content_type => self["#{name}_type"],
+ })
end
- end
+ end.tap(&:clear)
+ end
- @attachment_assignments.clear
+ def destroy_nil_attachments
+ nil_attachments.each { |name| grid.delete(self["#{name}_id"]) }.tap(&:clear)
end
- def destroy_attached_files
- self.class.attachment_names.each do |name|
- grid.delete(self["#{name}_id"])
- end
+ def destroy_all_attachments
+ self.class.attachment_names.each { |name| grid.delete(self["#{name}_id"]) }
end
end
class AttachmentProxy
def initialize(instance, name)
@@ -92,7 +106,11 @@
end
def method_missing(method, *args, &block)
grid_io.send(method, *args, &block)
end
+ end
+
+ def self.file_name(file)
+ file.respond_to?(:original_filename) ? file.original_filename : File.basename(file.path)
end
end