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 = {})