paperclip_database_storage 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,3 @@
1
+ module PaperclipDatabaseStorage
2
+ VERSION = "3.0.0" unless defined? PaperclipDatabaseStorage::VERSION
3
+ 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: []