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