lib/paperclip/storage/database.rb in paperclip_database-1.0.5 vs lib/paperclip/storage/database.rb in paperclip_database-2.0.0

- old
+ new

@@ -1,63 +1,63 @@ module Paperclip module Storage # Store files in a database. - # + # # Usage is identical to the file system storage version, except: - # + # # 1. In your model specify the "database" storage option; for example: # has_attached_file :avatar, :storage => :database - # + # # The files will be stored in a new database table named with the plural attachment name # by default, "avatars" in this example. - # + # # 2. You need to create this new storage table with at least these columns: # - file_contents # - style # - the primary key for the parent model (e.g. user_id) - # + # # Note the "binary" migration will not work for the LONGBLOG type in MySQL for the # file_cotents column. You may need to craft a SQL statement for your migration, # depending on which database server you are using. Here's an example migration for MySQL: - # + # # create_table :avatars do |t| # t.string :style # t.integer :user_id # t.timestamps # end # execute 'ALTER TABLE avatars ADD COLUMN file_contents LONGBLOB' - # + # # You can optionally specify any storage table name you want and whether or not deletion is done by cascading or not as follows: # has_attached_file :avatar, :storage => :database, :database_table => 'avatar_files', :cascade_deletion => true - # + # # 3. By default, URLs will be set to this pattern: # /:relative_root/:class/:attachment/:id?style=:style - # + # # Example: # /app-root-url/users/avatars/23?style=original - # + # # The idea here is that to retrieve a file from the database storage, you will need some # controller's code to be executed. - # + # # Once you pick a controller to use for downloading, you can add this line # to generate the download action for the default URL/action (the plural attachment name), # "avatars" in this example: # downloads_files_for :user, :avatar - # + # # Or you can write a download method manually if there are security, logging or other # requirements. - # + # # If you prefer a different URL for downloading files you can specify that in the model; e.g.: # has_attached_file :avatar, :storage => :database, :url => '/users/show_avatar/:id/:style' - # + # # 4. Add a route for the download to the controller which will handle downloads, if necessary. - # + # # The default URL, /:relative_root/:class/:attachment/:id?style=:style, will be matched by # the default route: :controller/:action/:id - # + # module Database - + def self.extended(base) base.instance_eval do setup_paperclip_files_model override_default_options base end @@ -73,14 +73,14 @@ end if !relative_url_root && ActionController::Base.respond_to?(:relative_url_root) ActionController::Base.relative_url_root end end - + ActiveRecord::Base.logger.info("[paperclip] Database Storage Initalized.") end - + def setup_paperclip_files_model #TODO: This fails when your model is in a namespace. @paperclip_files = "#{instance.class.name.underscore}_#{name.to_s}_paperclip_files" if !Object.const_defined?(@paperclip_files.classify) @paperclip_file = Object.const_set(@paperclip_files.classify, Class.new(::ActiveRecord::Base)) @@ -96,15 +96,15 @@ @paperclip_file = Object.const_get(@paperclip_files.classify) 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, :foreign_key => instance.class.table_name.classify.underscore + '_id' + instance.class.has_many @paperclip_files.to_sym, :foreign_key => instance.class.table_name.classify.underscore + '_id' end private :setup_paperclip_files_model - + 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 def override_default_options(base) @@ -112,32 +112,32 @@ @options[:url] = ":relative_root/:class/:attachment/:id?style=:style" end @options[:path] = ":database_path" end private :override_default_options - + def database_table @database_table end - + def database_path(style) paperclip_file = file_for(style) if paperclip_file "#{database_table}(id=#{paperclip_file.id},style=#{style.to_s})" else "#{database_table}(id=new,style=#{style.to_s})" end end - + def exists?(style = default_style) if original_filename !file_for(style).nil? else false end end - + # Returns representation of the data of the file assigned to the given # style, in the format most representative of the current storage. def to_file style = default_style if @queued_for_write[style] @queued_for_write[style] @@ -149,35 +149,42 @@ tempfile.rewind tempfile else nil end - + end alias_method :to_io, :to_file - + def file_for(style) db_result = instance.send("#{@paperclip_files}").send(:file_for, style.to_s).to_ary raise RuntimeError, "More than one result for #{style}" if db_result.size > 1 db_result.first end - + def file_contents(style) file_for(style).file_contents end - + def flush_writes ActiveRecord::Base.logger.info("[paperclip] Writing files for #{name}") @queued_for_write.each do |style, file| - paperclip_file = instance.send(@paperclip_files).send(:find_or_create_by_style, style.to_s) + case Rails::VERSION::STRING + when /^2/, /^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) + else # 4.x + raise "Rails version #{Rails::VERSION::STRING} is not supported (yet)" + end paperclip_file.file_contents = file.read paperclip_file.save! instance.reload - end + end @queued_for_write = {} end - + def flush_deletes #:nodoc: 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) @@ -187,10 +194,10 @@ @paperclip_file.destroy $1 end end @queued_for_delete = [] end - + module ControllerClassMethods def self.included(base) base.extend(self) end def downloads_files_for(model, attachment, options = {})