sga_paperclippolymorph 0.1.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/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/generators/polymorphic_paperclip/USAGE +8 -0
- data/generators/polymorphic_paperclip/polymorphic_paperclip_generator.rb +52 -0
- data/generators/polymorphic_paperclip/templates/migration.rb +28 -0
- data/lib/sga/acts_as_polymorphic_paperclip.rb +113 -0
- data/lib/sga/asset.rb +67 -0
- data/lib/sga/attaching.rb +16 -0
- data/lib/sga_paperclippolymorph.rb +4 -0
- data/test/helper.rb +10 -0
- data/test/test_sga_paperclippolymorph.rb +7 -0
- metadata +92 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 tim.teng
|
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.rdoc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
= sga_paperclippolymorph
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Note on Patches/Pull Requests
|
6
|
+
|
7
|
+
* Fork the project.
|
8
|
+
* Make your feature addition or bug fix.
|
9
|
+
* Add tests for it. This is important so I don't break it in a
|
10
|
+
future version unintentionally.
|
11
|
+
* Commit, do not mess with rakefile, version, or history.
|
12
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
13
|
+
* Send me a pull request. Bonus points for topic branches.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2010 tim.teng. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "sga_paperclippolymorph"
|
8
|
+
gem.summary = %Q{gem version of paperclippolymorph for sga company}
|
9
|
+
gem.description = %Q{gem version of paperclippolymorph for sga company}
|
10
|
+
gem.email = "tim.rubist@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/tteng/sga_paperclippolymorph"
|
12
|
+
gem.authors = ["tim.teng"]
|
13
|
+
#gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
14
|
+
gem.add_runtime_dependency "paperclip", ">= 2.3.1.1"
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'rake/testtask'
|
23
|
+
Rake::TestTask.new(:test) do |test|
|
24
|
+
test.libs << 'lib' << 'test'
|
25
|
+
test.pattern = 'test/**/test_*.rb'
|
26
|
+
test.verbose = true
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
require 'rcov/rcovtask'
|
31
|
+
Rcov::RcovTask.new do |test|
|
32
|
+
test.libs << 'test'
|
33
|
+
test.pattern = 'test/**/test_*.rb'
|
34
|
+
test.verbose = true
|
35
|
+
end
|
36
|
+
rescue LoadError
|
37
|
+
task :rcov do
|
38
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
task :test => :check_dependencies
|
43
|
+
|
44
|
+
task :default => :test
|
45
|
+
|
46
|
+
require 'rake/rdoctask'
|
47
|
+
Rake::RDocTask.new do |rdoc|
|
48
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
49
|
+
|
50
|
+
rdoc.rdoc_dir = 'rdoc'
|
51
|
+
rdoc.title = "sga_paperclippolymorph #{version}"
|
52
|
+
rdoc.rdoc_files.include('README*')
|
53
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class PolymorphicPaperclipGenerator < Rails::Generator::Base
|
2
|
+
def initialize(runtime_args, runtime_options = {})
|
3
|
+
super
|
4
|
+
end
|
5
|
+
|
6
|
+
def manifest
|
7
|
+
recorded_session = record do |m|
|
8
|
+
|
9
|
+
unless has_rspec?
|
10
|
+
puts " All test for PolymorphicPaperclip are written in rSpec."
|
11
|
+
puts " Consider installing rSpec and the rSpec on rails plugin."
|
12
|
+
end
|
13
|
+
|
14
|
+
unless options[:skip_migration]
|
15
|
+
m.migration_template 'migration.rb', 'db/migrate',
|
16
|
+
:assigns => { :migration_name => "PolymorphicPaperclipMigration" },
|
17
|
+
:migration_file_name => "polymorphic_paperclip_migration"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
action = nil
|
22
|
+
action = $0.split("/")[1]
|
23
|
+
case action
|
24
|
+
when "generate"
|
25
|
+
puts
|
26
|
+
puts ("-" * 70)
|
27
|
+
puts "Success!"
|
28
|
+
puts
|
29
|
+
puts "Dont't Forget to:"
|
30
|
+
puts " - Add the acts_as_polymorphic_paperclip to the model that accepts assets"
|
31
|
+
puts " You will no longer need the has_attached_file argument in your model once you"
|
32
|
+
puts " add this plugin."
|
33
|
+
puts
|
34
|
+
unless options[:skip_migration]
|
35
|
+
puts " - Run the migration."
|
36
|
+
puts " rake db:migrate"
|
37
|
+
end
|
38
|
+
puts
|
39
|
+
puts
|
40
|
+
puts ("-" * 70)
|
41
|
+
puts
|
42
|
+
else
|
43
|
+
puts
|
44
|
+
end
|
45
|
+
|
46
|
+
recorded_session end
|
47
|
+
|
48
|
+
def has_rspec?
|
49
|
+
options[:rspec] || (File.exist?('spec') && File.directory?('spec'))
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class <%= migration_name %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table "assets" do |t|
|
4
|
+
t.string "data_file_name"
|
5
|
+
t.string "data_content_type"
|
6
|
+
t.integer "data_file_size"
|
7
|
+
t.integer "attachings_count", :default => 0
|
8
|
+
t.datetime "created_at"
|
9
|
+
t.datetime "data_updated_at"
|
10
|
+
end
|
11
|
+
|
12
|
+
create_table "attachings" do |t|
|
13
|
+
t.integer "attachable_id"
|
14
|
+
t.integer "asset_id"
|
15
|
+
t.string "attachable_type"
|
16
|
+
t.datetime "created_at"
|
17
|
+
t.datetime "updated_at"
|
18
|
+
end
|
19
|
+
|
20
|
+
add_index "attachings", ["asset_id"], :name => "index_attachings_on_asset_id"
|
21
|
+
add_index "attachings", ["attachable_id"], :name => "index_attachings_on_attachable_id"
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.down
|
25
|
+
drop_table :assets
|
26
|
+
drop_table :attachings
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module LocusFocus
|
2
|
+
module Acts #:nodoc: all
|
3
|
+
module PolymorphicPaperclip
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
# Extends the model to afford the ability to associate other records with the receiving record.
|
10
|
+
#
|
11
|
+
# This module needs the paperclip plugin to work
|
12
|
+
# http://www.thoughtbot.com/projects/paperclip
|
13
|
+
def acts_as_polymorphic_paperclip(options = {})
|
14
|
+
write_inheritable_attribute(:acts_as_polymorphic_paperclip_options, {
|
15
|
+
:counter_cache => options[:counter_cache],
|
16
|
+
:styles => options[:styles]
|
17
|
+
})
|
18
|
+
class_inheritable_reader :acts_as_polymorphic_paperclip_options
|
19
|
+
|
20
|
+
has_many :attachings, :as => :attachable, :dependent => :destroy
|
21
|
+
has_many :assets, :through => :attachings do
|
22
|
+
def attach(asset_id)
|
23
|
+
asset_id = extract_id(asset_id)
|
24
|
+
asset = Asset.find(asset_id)
|
25
|
+
@owner.assets << asset
|
26
|
+
@owner.assets(true)
|
27
|
+
end
|
28
|
+
|
29
|
+
def detach(asset_id, delete_if_no_attachings = false)
|
30
|
+
asset_id = extract_id(asset_id)
|
31
|
+
attaching = @owner.attachings.find(:first, :conditions => ['asset_id = ?', asset_id])
|
32
|
+
attachable = attaching.attachable
|
33
|
+
raise ActiveRecord::RecordNotFound unless attaching
|
34
|
+
result = attaching.destroy
|
35
|
+
|
36
|
+
asset = Asset.find(asset_id)
|
37
|
+
if asset.attachings.empty? && delete_if_no_attachings# delete if no longer attached to anything
|
38
|
+
override_default_styles, normalised_styles = attachable.override_default_styles?(asset.name)
|
39
|
+
asset.data.instance_variable_set("@styles", normalised_styles) if override_default_styles
|
40
|
+
asset.data.send(:queue_existing_for_delete)
|
41
|
+
asset.data.send(:flush_deletes)
|
42
|
+
asset.save # needed to permanently remove file name and urls
|
43
|
+
end
|
44
|
+
result
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
def extract_id(obj)
|
49
|
+
return obj.id unless obj.class == Fixnum || obj.class == String
|
50
|
+
obj.to_i if obj.to_i > 0
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Virtual attribute for the ActionController::UploadedStringIO
|
55
|
+
# which consists of these attributes "content_type", "original_filename" & "original_path"
|
56
|
+
# content_type: image/png
|
57
|
+
# original_filename: 64x16.png
|
58
|
+
# original_path: 64x16.png
|
59
|
+
attr_accessor :data
|
60
|
+
|
61
|
+
include LocusFocus::Acts::PolymorphicPaperclip::InstanceMethods
|
62
|
+
end
|
63
|
+
end
|
64
|
+
module InstanceMethods
|
65
|
+
def after_save
|
66
|
+
super
|
67
|
+
Asset.transaction do
|
68
|
+
if data.is_a?(Array)
|
69
|
+
data.each do |data_item|
|
70
|
+
create_and_save_asset(data_item) unless data_item.nil? || data_item.blank?
|
71
|
+
end
|
72
|
+
else
|
73
|
+
create_and_save_asset(data)
|
74
|
+
end
|
75
|
+
end unless data.nil? || data.blank?
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_and_save_asset(data_item)
|
79
|
+
the_asset = Asset.find_or_initialize_by_data_file_name(data_item.original_filename)
|
80
|
+
override_default_styles, normalised_styles = override_default_styles?(data_item.original_filename)
|
81
|
+
the_asset.data.instance_variable_set("@styles", normalised_styles) if override_default_styles
|
82
|
+
the_asset.data = data_item
|
83
|
+
if the_asset.save
|
84
|
+
|
85
|
+
# This association may be saved more than once within the same request / response
|
86
|
+
# cycle, which leads to needless DB calls. Now we'll clear out the data attribute
|
87
|
+
# once the record is successfully saved any subsequent calls will be ignored.
|
88
|
+
data_item = nil
|
89
|
+
Attaching.find_or_create_by_asset_id_and_attachable_type_and_attachable_id(:asset_id => the_asset.id, :attachable_type => self.class.to_s, :attachable_id => self.id)
|
90
|
+
assets(true) # implicit reloading
|
91
|
+
end
|
92
|
+
end
|
93
|
+
def override_default_styles?(filename)
|
94
|
+
if !acts_as_polymorphic_paperclip_options[:styles].nil?
|
95
|
+
normalised_styles = {}
|
96
|
+
acts_as_polymorphic_paperclip_options[:styles].each do |name, args|
|
97
|
+
dimensions, format = [args, nil].flatten[0..1]
|
98
|
+
format = nil if format.blank?
|
99
|
+
if filename.match(/\.pdf$/) # remove crop commands if file is a PDF (this fails with Imagemagick)
|
100
|
+
args.gsub!(/#/ , "")
|
101
|
+
format = "png"
|
102
|
+
end
|
103
|
+
normalised_styles[name] = { :processors => [:thumbnail], :geometry => dimensions, :format => format }
|
104
|
+
end
|
105
|
+
return true, normalised_styles
|
106
|
+
else
|
107
|
+
return false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
data/lib/sga/asset.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
gem 'paperclip', ">=2.3.1.1"
|
2
|
+
require 'paperclip'
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
class Asset < ActiveRecord::Base
|
6
|
+
has_many :attachings, :dependent => :destroy
|
7
|
+
|
8
|
+
has_attached_file :data,
|
9
|
+
:styles => {
|
10
|
+
:tiny => "64x64>",
|
11
|
+
:small => "176x112>",
|
12
|
+
:medium => "630x630>",
|
13
|
+
:large => "1024x1024>"
|
14
|
+
}
|
15
|
+
|
16
|
+
def url(*args)
|
17
|
+
data.url(*args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
data_file_name
|
22
|
+
end
|
23
|
+
|
24
|
+
def content_type
|
25
|
+
data_content_type
|
26
|
+
end
|
27
|
+
|
28
|
+
def browser_safe?
|
29
|
+
%w(jpg gif png).include?(url.split('.').last.sub(/\?.+/, "").downcase)
|
30
|
+
end
|
31
|
+
alias_method :web_safe?, :browser_safe?
|
32
|
+
|
33
|
+
# This method will replace one of the existing thumbnails with an file provided.
|
34
|
+
def replace_style(style, file)
|
35
|
+
style = style.downcase.to_sym
|
36
|
+
if data.styles.keys.include?(style)
|
37
|
+
if File.exist?(RAILS_ROOT + '/public' + a.data(style))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# This method assumes you have images that corespond to the filetypes.
|
43
|
+
# For example "image/png" becomes "image-png.png"
|
44
|
+
def icon
|
45
|
+
"#{data_content_type.gsub(/[\/\.]/,'-')}.png"
|
46
|
+
end
|
47
|
+
|
48
|
+
def detach(attached)
|
49
|
+
a = attachings.find(:first, :conditions => ["attachable_id = ? AND attachable_type = ?", attached, attached.class.to_s])
|
50
|
+
raise ActiveRecord::RecordNotFound unless a
|
51
|
+
a.destroy
|
52
|
+
end
|
53
|
+
|
54
|
+
def path
|
55
|
+
File.join RAILS_ROOT, 'public', self.url_without_random
|
56
|
+
end
|
57
|
+
|
58
|
+
def file_md5sum
|
59
|
+
#path = File.join RAILS_ROOT, 'public', self.url_without_random
|
60
|
+
IO.popen("md5sum #{path} | awk '{print $1}'"){|f| f.gets.strip}
|
61
|
+
end
|
62
|
+
|
63
|
+
def url_without_random format=:original
|
64
|
+
self.url(format) =~ /^(.*)\?\d*$/ ? $1 : self.url(format)
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Attaching < ActiveRecord::Base
|
2
|
+
belongs_to :asset, :counter_cache => true
|
3
|
+
belongs_to :attachable, :polymorphic => true
|
4
|
+
|
5
|
+
def after_create
|
6
|
+
if self.attachable.acts_as_polymorphic_paperclip_options[:counter_cache]
|
7
|
+
self.attachable.class.increment_counter(:assets_count, self.attachable.id)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def after_destroy
|
12
|
+
if self.attachable.acts_as_polymorphic_paperclip_options[:counter_cache]
|
13
|
+
self.attachable.class.decrement_counter(:assets_count, self.attachable.id)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/test/helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sga_paperclippolymorph
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- tim.teng
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-04-07 00:00:00 +08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: paperclip
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 2
|
29
|
+
- 3
|
30
|
+
- 1
|
31
|
+
- 1
|
32
|
+
version: 2.3.1.1
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
description: gem version of paperclippolymorph for sga company
|
36
|
+
email: tim.rubist@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- LICENSE
|
43
|
+
- README.rdoc
|
44
|
+
files:
|
45
|
+
- .document
|
46
|
+
- .gitignore
|
47
|
+
- LICENSE
|
48
|
+
- README.rdoc
|
49
|
+
- Rakefile
|
50
|
+
- VERSION
|
51
|
+
- generators/polymorphic_paperclip/USAGE
|
52
|
+
- generators/polymorphic_paperclip/polymorphic_paperclip_generator.rb
|
53
|
+
- generators/polymorphic_paperclip/templates/migration.rb
|
54
|
+
- lib/sga/acts_as_polymorphic_paperclip.rb
|
55
|
+
- lib/sga/asset.rb
|
56
|
+
- lib/sga/attaching.rb
|
57
|
+
- lib/sga_paperclippolymorph.rb
|
58
|
+
- test/helper.rb
|
59
|
+
- test/test_sga_paperclippolymorph.rb
|
60
|
+
has_rdoc: true
|
61
|
+
homepage: http://github.com/tteng/sga_paperclippolymorph
|
62
|
+
licenses: []
|
63
|
+
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options:
|
66
|
+
- --charset=UTF-8
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
requirements: []
|
84
|
+
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 1.3.6
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: gem version of paperclippolymorph for sga company
|
90
|
+
test_files:
|
91
|
+
- test/test_sga_paperclippolymorph.rb
|
92
|
+
- test/helper.rb
|