paperclip_database_storage 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT_LICENSE +20 -0
- data/README.md +59 -0
- data/Rakefile +23 -0
- data/app/controllers/paperclip_database_storage/attachments_controller.rb +19 -0
- data/app/models/paperclip_database_storage/attachment.rb +11 -0
- data/config/routes.rb +26 -0
- data/db/migrate/create_paperclip_database_storage_attachments.rb +31 -0
- data/lib/paperclip_database_storage.rb +11 -0
- data/lib/paperclip_database_storage/storage/database.rb +87 -0
- data/lib/paperclip_database_storage/version.rb +3 -0
- data/lib/tasks/paperclip_database_storage.rake +21 -0
- data/paperclip_database_storage.gemspec +22 -0
- metadata +73 -0
data/MIT_LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 [Martin Caruso]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
paperclip_database_storage
|
2
|
+
==================
|
3
|
+
|
4
|
+
Adds support for storing a paperclip attachment file contents in a database table.
|
5
|
+
|
6
|
+
Requirements
|
7
|
+
------------
|
8
|
+
|
9
|
+
paperclip_database_storage requires [Paperclip](https://github.com/thoughtbot/paperclip) version **>= 3.2.0**.
|
10
|
+
|
11
|
+
Installation
|
12
|
+
------------
|
13
|
+
|
14
|
+
paperclip_database_storage is distributed as a gem, and that is how it should be used in your app.
|
15
|
+
|
16
|
+
Include the gem in your `Gemfile`, from rubygems:
|
17
|
+
|
18
|
+
gem 'paperclip_database_storage', '>= 3.2.0'
|
19
|
+
|
20
|
+
Or, get the master branch from the repository:
|
21
|
+
|
22
|
+
gem 'paperclip_database_storage', :git => 'git://github.com/gokuu/paperclip_database_storage.git'
|
23
|
+
|
24
|
+
Usage
|
25
|
+
-----
|
26
|
+
|
27
|
+
All you need to do is, when defining a [Paperclip](https://github.com/thoughtbot/paperclip) attachment, set its `:storage` option as `:database`:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class MyModel < ActiveRecord::Base
|
31
|
+
has_attached_file :attachment,
|
32
|
+
:storage => :database,
|
33
|
+
:styles => {
|
34
|
+
:medium => "300x300>",
|
35
|
+
:thumb => "100x100>"
|
36
|
+
},
|
37
|
+
:url => "/:class/:attachment/:id/:style/:basename.:extension"
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
Remarks
|
42
|
+
-------
|
43
|
+
|
44
|
+
The migration defined by `paperclip_database_storage` contains several indexes, as every possible combination of the fields that can identify a single attachment. This should help getting an attachment as quickly as possible using any combination of parameters
|
45
|
+
|
46
|
+
Limitations
|
47
|
+
-----------
|
48
|
+
|
49
|
+
* Paperclip-database currently only supports one database attachment per model.
|
50
|
+
* Although you can define a custom :url option for getting the attachment, make sure you define one that uniquelly identifies each attachment, otherwise the plugin will raise an Exception.
|
51
|
+
|
52
|
+
TO-DO
|
53
|
+
-----
|
54
|
+
|
55
|
+
* Add tests!
|
56
|
+
* Add support for more than one database attachment per model
|
57
|
+
* Enable defining a separate table for each different attachment
|
58
|
+
|
59
|
+
Copyright (c) 2012 [Pedro Rodrigues], released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the paperclip_database gem'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.libs << 'test'
|
12
|
+
t.pattern = 'test/**/*_test.rb'
|
13
|
+
t.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generate documentation for the paperclip_database gem'
|
17
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = 'Paperclipdb'
|
20
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
+
rdoc.rdoc_files.include('README')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class PaperclipDatabaseStorage::AttachmentsController < ApplicationController
|
2
|
+
def get_attachment
|
3
|
+
conditions = {}
|
4
|
+
conditions[:attached_type] = params[:class].singularize.camelize if params[:class]
|
5
|
+
conditions[:attached_id] = params[:id] if params[:id]
|
6
|
+
conditions[:attached_id] ||= params[:id_partition].gsub(/\//, '').to_i if params[:id_partition]
|
7
|
+
conditions[:attachment_name] = params[:attachment].singularize if params[:attachment]
|
8
|
+
conditions[:style] = params[:style] if params[:style]
|
9
|
+
|
10
|
+
|
11
|
+
attachments = PaperclipDatabaseStorage::Attachment.where(conditions)
|
12
|
+
|
13
|
+
raise ActionController::RoutingError.new('Image not Found') if attachments.empty?
|
14
|
+
raise ActionController::RoutingError.new('Too many images found. Check your route definition') if attachments.length > 1
|
15
|
+
|
16
|
+
attachment = attachments.first
|
17
|
+
send_data attachment.file_data, :type => attachment.content_type
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module PaperclipDatabaseStorage
|
2
|
+
class Attachment < ActiveRecord::Base
|
3
|
+
belongs_to :attached, :polymorphic => true
|
4
|
+
|
5
|
+
attr_accessible :style, :file_data, :content_type, :file_size, :attachment_name
|
6
|
+
|
7
|
+
def self.table_name
|
8
|
+
return 'paperclip_database_storage_attachments'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
# Dynamically create routes based on defined attachments
|
3
|
+
Rails.application.eager_load!
|
4
|
+
|
5
|
+
loaded_url_templates = []
|
6
|
+
must_create_default_route = false
|
7
|
+
|
8
|
+
Paperclip.classes_with_attachments.each do |class_name|
|
9
|
+
klass = class_name.constantize
|
10
|
+
|
11
|
+
klass.attachment_definitions.each do |attachment_name, definition|
|
12
|
+
must_create_default_route = true and next unless definition.has_key?(:url)
|
13
|
+
next if loaded_url_templates.include?(definition[:url])
|
14
|
+
|
15
|
+
loaded_url_templates << definition[:url]
|
16
|
+
|
17
|
+
#ap [klass.name, attachment_name, definition]
|
18
|
+
get definition[:url] => 'paperclip_database_storage/attachments#get_attachment'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Generate the default route, if necessary
|
23
|
+
if must_create_default_route
|
24
|
+
get Paperclip::Attachment.default_options[:url].gsub(/:id_partition/, '*id_partition') => 'paperclip_database_storage/attachments#get_attachment', :as => :default_pds
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class CreatePaperclipDatabaseStorageAttachments < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :paperclip_database_storage_attachments do |t|
|
4
|
+
t.string :attached_type, :null => false
|
5
|
+
t.integer :attached_id, :null => false
|
6
|
+
t.string :attachment_name, :null => false
|
7
|
+
t.string :style, :null => false
|
8
|
+
t.binary :file_data, :null => false
|
9
|
+
t.string :content_type
|
10
|
+
t.integer :file_size
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
add_index :paperclip_database_storage_attachments, [ :attached_type, :attached_id, :attachment_name, :style ], :unique => true, :name => :idx_attachments_1
|
14
|
+
add_index :paperclip_database_storage_attachments, [ :attached_type, :attached_id, :attachment_name ], :name => :idx_attachments_2
|
15
|
+
add_index :paperclip_database_storage_attachments, [ :attached_type, :attached_id ], :name => :idx_attachments_3
|
16
|
+
add_index :paperclip_database_storage_attachments, [ :attached_type ], :name => :idx_attachments_4
|
17
|
+
add_index :paperclip_database_storage_attachments, [ :attached_type, :attached_id, :style ], :name => :idx_attachments_5
|
18
|
+
add_index :paperclip_database_storage_attachments, [ :attached_type, :style ], :name => :idx_attachments_6
|
19
|
+
add_index :paperclip_database_storage_attachments, [ :style ], :name => :idx_attachments_7
|
20
|
+
add_index :paperclip_database_storage_attachments, [ :attached_type, :attachment_name, :style ], :name => :idx_attachments_8
|
21
|
+
add_index :paperclip_database_storage_attachments, [ :attachment_name, :style ], :name => :idx_attachments_9
|
22
|
+
add_index :paperclip_database_storage_attachments, [ :attachment_name ], :name => :idx_attachments_10
|
23
|
+
add_index :paperclip_database_storage_attachments, [ :attached_type, :attachment_name, :style ], :name => :idx_attachments_11
|
24
|
+
add_index :paperclip_database_storage_attachments, [ :attachment_name, :style ], :name => :idx_attachments_12
|
25
|
+
add_index :paperclip_database_storage_attachments, [ :style ], :name => :idx_attachments_13
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.down
|
29
|
+
drop_table :paperclip_database_storage_attachments
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
#require 'paperclip_database/storage.rb'
|
2
|
+
require 'paperclip_database_storage'
|
3
|
+
require 'paperclip_database_storage/storage/database'
|
4
|
+
require 'rails'
|
5
|
+
require 'paperclip'
|
6
|
+
|
7
|
+
# This will load the necessary models and controllers
|
8
|
+
module PaperclipDatabaseStorage
|
9
|
+
class Engine < Rails::Engine
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Paperclip
|
2
|
+
module Storage
|
3
|
+
module Database
|
4
|
+
def self.extended(base)
|
5
|
+
base.instance_eval do
|
6
|
+
override_default_options base
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def override_default_options(base)
|
11
|
+
@path = @url
|
12
|
+
end
|
13
|
+
|
14
|
+
private :override_default_options
|
15
|
+
|
16
|
+
def exists?(style = default_style)
|
17
|
+
return !get_attachment(style).nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
def path(style = default_style)
|
21
|
+
return style
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_attachment(style)
|
25
|
+
return PaperclipDatabaseStorage::Attachment.find(:first, :conditions => {
|
26
|
+
:style => style,
|
27
|
+
:attached_type => self.instance.class.name,
|
28
|
+
:attached_id => self.instance.id,
|
29
|
+
:attachment_name => self.get_attachment_definitions.keys.first
|
30
|
+
})
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_attachment_definitions
|
34
|
+
attachment_definitions = self.instance.class.attachment_definitions
|
35
|
+
|
36
|
+
if attachment_definitions.select { |k,v| v[:storage] == :database }.count > 1
|
37
|
+
raise Exception.new('paperclip-database does not support more than one attachment per model')
|
38
|
+
end
|
39
|
+
|
40
|
+
return attachment_definitions
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def to_file style = default_style
|
45
|
+
if @queued_for_write[style]
|
46
|
+
@queued_for_write[style]
|
47
|
+
elsif exists?(style)
|
48
|
+
attachment = get_attachment(style)
|
49
|
+
tempfile = Tempfile.new attachment.base_name
|
50
|
+
tempfile.write attachment.file_data
|
51
|
+
tempfile
|
52
|
+
else
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def flush_writes
|
58
|
+
puts("[paperclip] Writing files #{@queued_for_write.count}")
|
59
|
+
attachment_definitions = get_attachment_definitions
|
60
|
+
|
61
|
+
@queued_for_write.each do |style, file|
|
62
|
+
puts("[paperclip] Writing files for #{file} #{style}")
|
63
|
+
|
64
|
+
PaperclipDatabaseStorage::Attachment.new do |a|
|
65
|
+
a.attached_type = self.instance.class.name
|
66
|
+
a.attached_id = self.instance.id
|
67
|
+
a.style = style
|
68
|
+
a.content_type = self.instance_variable_get("@_#{self.name.to_s}_content_type")
|
69
|
+
a.attachment_name = attachment_definitions.keys.first
|
70
|
+
a.file_size = file.size
|
71
|
+
a.file_data = file.read
|
72
|
+
end.save
|
73
|
+
end
|
74
|
+
@queued_for_write = {}
|
75
|
+
end
|
76
|
+
|
77
|
+
def flush_deletes
|
78
|
+
@queued_for_delete.each do |style|
|
79
|
+
puts("[paperclip] Deleting files for #{style}")
|
80
|
+
attachment = get_attachment(style)
|
81
|
+
attachment.destroy if !attachment.nil?
|
82
|
+
end
|
83
|
+
@queued_for_delete = []
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
namespace :'paperclip_database_storage' do
|
2
|
+
desc 'Copy necessary migrations from paperclip_database_storage to the rails project'
|
3
|
+
task :setup => :environment do
|
4
|
+
plugin_root = File.dirname(File.dirname(File.dirname(__FILE__)))
|
5
|
+
|
6
|
+
Dir[File.join(plugin_root, 'db', 'migrate', '*.rb')].each do |file|
|
7
|
+
# First, check if the migration has already been copied
|
8
|
+
if Dir[File.join('db', 'migrate', "*#{File.basename(file)}*")].any?
|
9
|
+
puts "Migration #{File.basename(file)} has already been copied, skipping..."
|
10
|
+
else
|
11
|
+
dest_file = "#{Time.now.strftime('%Y%m%d%H%M%S')}_#{File.basename(file)}"
|
12
|
+
dest_dir = File.join(Rails.root, 'db', 'migrate')
|
13
|
+
|
14
|
+
puts "Copying #{File.basename(file)} to #{dest_file}"
|
15
|
+
|
16
|
+
FileUtils.mkdir_p dest_dir
|
17
|
+
FileUtils.cp(file, File.join(dest_dir, dest_file))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path("../lib", __FILE__)
|
2
|
+
require 'paperclip_database_storage/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'paperclip_database_storage'
|
6
|
+
s.version = PaperclipDatabaseStorage::VERSION
|
7
|
+
|
8
|
+
s.authors = ['Pedro Rodrigues']
|
9
|
+
s.date = '2012-10-01'
|
10
|
+
s.summary = 'Database storage support for paperclip file attachment plugin'
|
11
|
+
s.description = 'Adds support for storing the contents of files attachment via paperclip plugin on the database'
|
12
|
+
s.email = 'pedro@bbde.org'
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.require_paths = ['lib']
|
17
|
+
s.required_ruby_version = ">= 1.9.2"
|
18
|
+
|
19
|
+
s.homepage = 'http://github.com/gokuu/paperclip_database_storage'
|
20
|
+
|
21
|
+
s.add_dependency 'paperclip', [">= 3.0.0"]
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: paperclip_database_storage
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 3.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Pedro Rodrigues
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-01 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: paperclip
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.0.0
|
30
|
+
description: Adds support for storing the contents of files attachment via paperclip
|
31
|
+
plugin on the database
|
32
|
+
email: pedro@bbde.org
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- MIT_LICENSE
|
38
|
+
- README.md
|
39
|
+
- Rakefile
|
40
|
+
- app/controllers/paperclip_database_storage/attachments_controller.rb
|
41
|
+
- app/models/paperclip_database_storage/attachment.rb
|
42
|
+
- config/routes.rb
|
43
|
+
- db/migrate/create_paperclip_database_storage_attachments.rb
|
44
|
+
- lib/paperclip_database_storage.rb
|
45
|
+
- lib/paperclip_database_storage/storage/database.rb
|
46
|
+
- lib/paperclip_database_storage/version.rb
|
47
|
+
- lib/tasks/paperclip_database_storage.rake
|
48
|
+
- paperclip_database_storage.gemspec
|
49
|
+
homepage: http://github.com/gokuu/paperclip_database_storage
|
50
|
+
licenses: []
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 1.9.2
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
requirements: []
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.8.24
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Database storage support for paperclip file attachment plugin
|
73
|
+
test_files: []
|