lib/paperclip/storage/database.rb in paperclip_database-2.2.2 vs lib/paperclip/storage/database.rb in paperclip_database-2.3.0

- old
+ new

@@ -56,11 +56,13 @@ # module Database def self.extended(base) base.instance_eval do - setup_paperclip_files_model + setup_attachment_class + setup_paperclip_file_model + setup_paperclip_files_association override_default_options base end Paperclip.interpolates(:database_path) do |attachment, style| attachment.database_path(style) end @@ -77,34 +79,46 @@ end ActiveRecord::Base.logger.info("[paperclip] Database Storage Initalized.") end - def setup_paperclip_files_model - # If the model is in a namespace, look up that module - if instance.class.name.include?('::') - module_name = PaperclipDatabase::deconstantize(instance.class.name) - @paperclip_class_module = module_name.constantize rescue Object + def setup_paperclip_files_association + @paperclip_files_association_name = 'paperclip_files' + @database_table = @paperclip_file_model.table_name + #FIXME: This fails when using set_table_name "<myname>" in your model + #FIXME: This should be fixed in ActiveRecord... + instance.class.has_many(@paperclip_files_association_name.to_sym, + :class_name => @paperclip_file_model.name, + :foreign_key => instance.class.table_name.classify.underscore + '_id' + ) + end + private :setup_paperclip_files_association + + def setup_paperclip_file_model + class_name = "#{instance.class.table_name.singularize}_#{name.to_s}_paperclip_file".classify + if @attachment_class.const_defined?(class_name, false) + @paperclip_file_model = @attachment_class.const_get(class_name, false) else - @paperclip_class_module = Object + @paperclip_file_model = @attachment_class.const_set(class_name, Class.new(::ActiveRecord::Base)) + @paperclip_file_model.table_name = @options[:database_table] || name.to_s.pluralize + @paperclip_file_model.validates_uniqueness_of :style, :scope => instance.class.table_name.classify.underscore + '_id' + @paperclip_file_model.scope :file_for, lambda {|style| @paperclip_file_model.where('style = ?', style) } end + end + private :setup_paperclip_file_model - @paperclip_files = "#{instance.class.name.demodulize.underscore}_#{name.to_s}_paperclip_files" - if !@paperclip_class_module.const_defined?(@paperclip_files.classify) - @paperclip_file = @paperclip_class_module.const_set(@paperclip_files.classify, Class.new(::ActiveRecord::Base)) - @paperclip_file.table_name = @options[:database_table] || name.to_s.pluralize - @paperclip_file.validates_uniqueness_of :style, :scope => instance.class.table_name.classify.underscore + '_id' - @paperclip_file.scope :file_for, lambda {|style| @paperclip_file.where('style = ?', style) } - else - @paperclip_file = @paperclip_class_module.const_get(@paperclip_files.classify) + def setup_attachment_class + instance.class.ancestors.each do |ancestor| + # Pick the top-most definition like + # Paperclip::AttachmentRegistry#definitions_for + names_for_ancestor = ancestor.attachment_definitions.keys rescue [] + if names_for_ancestor.member?(name) + @attachment_class = ancestor + end end - @database_table = @paperclip_file.table_name - #FIXME: This fails when using set_table_name "<myname>" in your model - #FIXME: This should be fixed in ActiveRecord... - instance.class.has_many @paperclip_files.to_sym, :class_name => @paperclip_file.name, :foreign_key => instance.class.table_name.classify.underscore + '_id' end - private :setup_paperclip_files_model + private :setup_attachment_class def copy_to_local_file(style, dest_path) File.open(dest_path, 'wb+'){|df| to_file(style).tap{|sf| File.copy_stream(sf, df); sf.close;sf.unlink} } end @@ -129,11 +143,11 @@ end end def exists?(style = default_style) if original_filename - instance.send("#{@paperclip_files}").where(:style => style).exists? + instance.send("#{@paperclip_files_association_name}").where(:style => style).exists? else false end end @@ -155,11 +169,11 @@ end alias_method :to_io, :to_file def file_for(style) - db_result = instance.send("#{@paperclip_files}").send(:file_for, style.to_s) + db_result = instance.send("#{@paperclip_files_association_name}").send(:file_for, style.to_s) raise RuntimeError, "More than one result for #{style}" if db_result.size > 1 db_result.first end def file_contents(style = default_style) @@ -167,17 +181,17 @@ end def flush_writes ActiveRecord::Base.logger.info("[paperclip] Writing files for #{name}") @queued_for_write.each do |style, file| - case Rails::VERSION::STRING - when /^3/ - paperclip_file = instance.send(@paperclip_files).send(:find_or_create_by_style, style.to_s) - when /^4/ - paperclip_file = instance.send(@paperclip_files).send(:find_or_create_by, style: style.to_s) + case ActiveModel::VERSION::MAJOR + when 3 + paperclip_file = instance.send(@paperclip_files_association_name).send(:find_or_create_by_style, style.to_s) + when 4 + paperclip_file = instance.send(@paperclip_files_association_name).send(:find_or_create_by, style: style.to_s) else - raise "Rails version #{Rails::VERSION::STRING} is not supported (yet)" + raise "ActiveModel version #{ActiveModel::VERSION::STRING} is not supported (yet)" end paperclip_file.file_contents = file.read paperclip_file.save! instance.reload end @@ -188,13 +202,13 @@ ActiveRecord::Base.logger.info("[paperclip] Deleting files for #{name}") @queued_for_delete.uniq! ##This is apparently necessary for paperclip v 3.x @queued_for_delete.each do |path| /id=([0-9]+)/.match(path) if @options[:cascade_deletion] && !instance.class.exists?(instance.id) - raise RuntimeError, "Deletion has not been done by through cascading." if @paperclip_file.exists?($1) + raise RuntimeError, "Deletion has not been done by through cascading." if @paperclip_file_model.exists?($1) else - @paperclip_file.destroy $1 + @paperclip_file_model.destroy $1 end end @queued_for_delete = [] end @@ -202,10 +216,11 @@ def self.included(base) base.extend(self) end def downloads_files_for(model, attachment, options = {}) define_method("#{attachment.to_s.pluralize}") do - model_record = Object.const_get(model.to_s.camelize.to_sym).find(params[:id]) + #FIXME: Handling Namespaces + model_record = Object.const_get(model.to_s.camelize.to_sym, false).find(params[:id]) style = params[:style] ? params[:style] : 'original' send_data model_record.send(attachment).file_contents(style), :filename => model_record.send("#{attachment}_file_name".to_sym), :type => model_record.send("#{attachment}_content_type".to_sym) end