papermill 0.5.7
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/.gitignore +5 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +94 -0
- data/Rakefile +69 -0
- data/VERSION +1 -0
- data/app/controllers/papermill_controller.rb +78 -0
- data/app/views/papermill/_asset.html.erb +11 -0
- data/app/views/papermill/_raw_asset.html.erb +1 -0
- data/app/views/papermill/_thumbnail_asset.html.erb +6 -0
- data/app/views/papermill/edit.html.erb +5 -0
- data/config/locales/papermill.yml +28 -0
- data/config/routes.rb +4 -0
- data/generators/papermill/USAGE +3 -0
- data/generators/papermill/papermill_generator.rb +22 -0
- data/generators/papermill/templates/migrate/papermill_migration.rb.erb +22 -0
- data/init.rb +1 -0
- data/install.rb +0 -0
- data/installation-template.txt +124 -0
- data/lib/core_extensions.rb +25 -0
- data/lib/papermill.rb +0 -0
- data/lib/papermill/form_builder.rb +101 -0
- data/lib/papermill/papermill_asset.rb +54 -0
- data/lib/papermill/papermill_helper.rb +48 -0
- data/lib/papermill/papermill_module.rb +177 -0
- data/papermill.gemspec +93 -0
- data/public/flashs/swfupload.swf +0 -0
- data/public/images/papermill/background.png +0 -0
- data/public/images/papermill/container-background.jpg +0 -0
- data/public/images/papermill/delete.png +0 -0
- data/public/images/papermill/upload-blank.png +0 -0
- data/public/images/papermill/upload.png +0 -0
- data/public/javascripts/papermill.js +83 -0
- data/public/stylesheets/papermill.css +33 -0
- data/rails/init.rb +13 -0
- data/tasks/papermill_tasks.rake +1 -0
- data/test/papermill_test.rb +9 -0
- data/test/test_helper.rb +3 -0
- data/uninstall.rb +1 -0
- metadata +135 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
module HashExtensions
|
2
|
+
def deep_merge(hash)
|
3
|
+
target = dup
|
4
|
+
hash.keys.each do |key|
|
5
|
+
if hash[key].is_a? Hash and self[key].is_a? Hash
|
6
|
+
target[key] = target[key].deep_merge(hash[key])
|
7
|
+
next
|
8
|
+
end
|
9
|
+
target[key] = hash[key]
|
10
|
+
end
|
11
|
+
target
|
12
|
+
end
|
13
|
+
end
|
14
|
+
module StringExtensions
|
15
|
+
def simple_sql_sanitizer
|
16
|
+
gsub(/\\/, '\&\&').gsub(/'/, "''")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module ObjectExtensions
|
21
|
+
# Nil if empty.
|
22
|
+
def nie
|
23
|
+
self.blank? ? nil : self
|
24
|
+
end
|
25
|
+
end
|
data/lib/papermill.rb
ADDED
File without changes
|
@@ -0,0 +1,101 @@
|
|
1
|
+
class ActionView::Helpers::FormBuilder
|
2
|
+
|
3
|
+
def assets_upload(key = nil, options = {})
|
4
|
+
papermill_upload_field key, { :thumbnail => false }.update(options)
|
5
|
+
end
|
6
|
+
def asset_upload(key = nil, options = {})
|
7
|
+
papermill_upload_field key, { :gallery => false, :thumbnail => false }.update(options)
|
8
|
+
end
|
9
|
+
def images_upload(key = nil, options = {})
|
10
|
+
papermill_upload_field key, options
|
11
|
+
end
|
12
|
+
def image_upload(key = nil, options = {})
|
13
|
+
papermill_upload_field key, { :gallery => false }.update(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def papermill_upload_field(key, options = {})
|
18
|
+
if key.is_a? Hash
|
19
|
+
options = key
|
20
|
+
key = nil
|
21
|
+
end
|
22
|
+
assetable = @template.instance_variable_get("@#{@object_name}")
|
23
|
+
options = if assetable && (association = (assetable.class.papermill_associations[key] || assetable.class.papermill_associations[:papermill_assets]))
|
24
|
+
association[:options].deep_merge(options)
|
25
|
+
else
|
26
|
+
raise Exception.new("Papermill: can't find #{key.to_s} association for #{assetable.class.to_s}.\n\n##{assetable.class.to_s.underscore}.rb\n#set either a catchall papermill association: \npapermill {your_option_hash}\n#or this specific association: \npapermill :#{key.to_s}, {your_option_hash}")
|
27
|
+
end
|
28
|
+
assetable_id = assetable && (assetable.id || assetable.timestamp) || nil
|
29
|
+
assetable_type = assetable && assetable.class.to_s.underscore || nil
|
30
|
+
id = "papermill_#{assetable_type}_#{assetable_id}_#{key ? key.to_s : 'nil'}"
|
31
|
+
if options[:thumbnail]
|
32
|
+
w = options[:thumbnail][:width] || options[:thumbnail][:height] && options[:thumbnail][:aspect_ratio] && (options[:thumbnail][:height] * options[:thumbnail][:aspect_ratio]).to_i || nil
|
33
|
+
h = options[:thumbnail][:height] || options[:thumbnail][:width] && options[:thumbnail][:aspect_ratio] && (options[:thumbnail][:width] / options[:thumbnail][:aspect_ratio]).to_i || nil
|
34
|
+
options[:thumbnail][:style] ||= (w || h) && "#{w || options[:thumbnail][:max_width]}x#{h || options[:thumbnail][:max_height]}>" || "original"
|
35
|
+
if options[:thumbnail][:inline_css]
|
36
|
+
size = []
|
37
|
+
size << "width:#{w}px" if w
|
38
|
+
size << "height:#{h}px" if h
|
39
|
+
size = size.join("; ")
|
40
|
+
@template.content_for :papermill_inline_css do
|
41
|
+
inline_css = ["\n"]
|
42
|
+
if options[:gallery]
|
43
|
+
vp = options[:gallery][:vpadding].to_i
|
44
|
+
hp = options[:gallery][:hpadding].to_i
|
45
|
+
vm = options[:gallery][:vmargin].to_i
|
46
|
+
hm = options[:gallery][:hmargin].to_i
|
47
|
+
b = options[:gallery][:border_thickness].to_i
|
48
|
+
gallery_width = (options[:gallery][:width] || w) && "width:#{options[:gallery][:width] || options[:gallery][:columns]*(w+(hp+hm+b)*2)}px;" || ""
|
49
|
+
gallery_height = (options[:gallery][:height] || h) && "#{options[:gallery][:autogrow] ? "" : "min-"}height:#{options[:gallery][:height] || options[:gallery][:lines]*(h+(vp+vm+b)*2)}px;" || ""
|
50
|
+
inline_css << %{##{id} { #{gallery_width} #{gallery_height} }}
|
51
|
+
inline_css << %{##{id} li { margin:#{vm}px #{hm}px; border-width:#{b}px; padding:#{vp}px #{hp}px; #{size}; }}
|
52
|
+
else
|
53
|
+
inline_css << %{##{id}, ##{id} li { #{size} }}
|
54
|
+
end
|
55
|
+
inline_css << %{##{id} .name { width:#{w || "100"}px; }}
|
56
|
+
inline_css.join("\n")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
html = []
|
61
|
+
|
62
|
+
conditions = {:assetable_type => assetable.class.sti_name, :assetable_id => assetable_id}
|
63
|
+
conditions.merge!({:assetable_key => key.to_s}) if key
|
64
|
+
asset_class = options[:class_name] && options[:class_name].to_s.constantize || association && association[:class] || PapermillAsset
|
65
|
+
create_url = @template.url_for(:controller => "/papermill", :action => "create", :escape => false, :asset_class => asset_class.to_s, :assetable_key => key, :assetable_id => assetable_id, :assetable_type => assetable_type, :gallery => (options[:gallery] != false), :thumbnail_style => (options[:thumbnail] && options[:thumbnail][:style]))
|
66
|
+
if assetable && assetable.new_record? && !@timestamped
|
67
|
+
html << self.hidden_field(:timestamp, :value => assetable.timestamp)
|
68
|
+
@timestamped = true
|
69
|
+
end
|
70
|
+
collection = asset_class.find(:all, :conditions => conditions, :order => "position")
|
71
|
+
|
72
|
+
html << %{<div style="height: #{options[:swfupload][:button_height]}px;"><span id="browse_for_#{id}" class="swf_button"></span></div>}
|
73
|
+
html << @template.content_tag(:ul, :id => id, :class => "papermill #{(options[:thumbnail] ? "papermill-thumb-container" : "papermill-asset-container")} #{(options[:gallery] ? "papermill-multiple-items" : "papermill-unique-item")}") {
|
74
|
+
@template.render :partial => "papermill/asset", :collection => collection, :locals => { :thumbnail_style => (options[:thumbnail] && options[:thumbnail][:style]) }
|
75
|
+
}
|
76
|
+
@template.content_for :papermill_inline_js do
|
77
|
+
%{
|
78
|
+
#{%{$("##{id}").sortable({update:function(){jQuery.ajax({async:true, data:jQuery(this).sortable('serialize'), dataType:'script', type:'post', url:'#{@template.controller.send("sort_papermill_url")}'})}})} if options[:gallery]}
|
79
|
+
new SWFUpload({
|
80
|
+
upload_id: "#{id}",
|
81
|
+
upload_url: "#{@template.escape_javascript create_url}",
|
82
|
+
file_size_limit: "#{options[:file_size_limit_mb].megabytes}",
|
83
|
+
file_types: "#{options[:images_only] ? '*.jpg;*.jpeg;*.png;*.gif' : ''}",
|
84
|
+
file_types_description: "#{options[:thumbnail] ? 'Images' : 'Files'}",
|
85
|
+
file_queue_limit: "#{!options[:gallery] ? '1' : '0'}",
|
86
|
+
file_queued_handler: Upload.file_queued,
|
87
|
+
file_dialog_complete_handler: Upload.file_dialog_complete,
|
88
|
+
upload_start_handler: Upload.upload_start,
|
89
|
+
upload_progress_handler: Upload.upload_progress,
|
90
|
+
upload_error_handler: Upload.upload_error,
|
91
|
+
upload_success_handler: Upload.upload_success,
|
92
|
+
upload_complete_handler: Upload.upload_complete,
|
93
|
+
button_placeholder_id : "browse_for_#{id}",
|
94
|
+
#{options[:swfupload].map{ |key, value| ["false", "true"].include?(value.to_s) ? "#{key.to_s}: #{value.to_s}" : "#{key.to_s}: '#{value.to_s}'" }.compact.join(", ")}
|
95
|
+
});
|
96
|
+
}
|
97
|
+
end
|
98
|
+
html.reverse! if options[:button_after_container]
|
99
|
+
html.join("\n")
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'stringex'
|
2
|
+
require 'paperclip'
|
3
|
+
require 'mime/types'
|
4
|
+
require 'acts_as_list'
|
5
|
+
|
6
|
+
class PapermillAsset < ActiveRecord::Base
|
7
|
+
acts_as_list :scope => 'assetable_key=\'#{assetable_key.to_s.simple_sql_sanitizer}\' AND assetable_id=#{assetable_id} AND assetable_type=\'#{assetable_type}\''
|
8
|
+
|
9
|
+
belongs_to :assetable, :polymorphic => true
|
10
|
+
before_destroy :destroy_files
|
11
|
+
|
12
|
+
Paperclip::Attachment.interpolations[:escaped_basename] = proc do |attachment, style|
|
13
|
+
Paperclip::Attachment.interpolations[:basename].call(attachment, style).to_url
|
14
|
+
end
|
15
|
+
|
16
|
+
has_attached_file :file,
|
17
|
+
:path => "#{Papermill::PAPERMILL_DEFAULTS[:public_root]}/#{Papermill::PAPERMILL_DEFAULTS[:papermill_prefix]}/#{Papermill::PAPERCLIP_INTERPOLATION_STRING}",
|
18
|
+
:url => "/#{Papermill::PAPERMILL_DEFAULTS[:papermill_prefix]}/#{Papermill::PAPERCLIP_INTERPOLATION_STRING}"
|
19
|
+
validates_attachment_presence :file
|
20
|
+
|
21
|
+
def swfupload_file=(data)
|
22
|
+
data.content_type = MIME::Types.type_for(data.original_filename).to_s
|
23
|
+
self.file = data
|
24
|
+
end
|
25
|
+
|
26
|
+
def id_partition
|
27
|
+
("%09d" % self.id).scan(/\d{3}/).join("/")
|
28
|
+
end
|
29
|
+
|
30
|
+
def name
|
31
|
+
file_file_name
|
32
|
+
end
|
33
|
+
|
34
|
+
def size
|
35
|
+
file_file_size
|
36
|
+
end
|
37
|
+
|
38
|
+
def url(style = nil)
|
39
|
+
file.url(style && CGI::escape(style.to_s))
|
40
|
+
end
|
41
|
+
|
42
|
+
def content_type
|
43
|
+
file_content_type && file_content_type.split("/")
|
44
|
+
end
|
45
|
+
|
46
|
+
def image?
|
47
|
+
content_type && content_type.first == "image" && content_type[1]
|
48
|
+
end
|
49
|
+
|
50
|
+
def destroy_files
|
51
|
+
system "rm -rf #{Papermill::papermill_interpolated_path({":id_partition" => self.id_partition}, ':id_partition')}/"
|
52
|
+
true
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module PapermillHelper
|
2
|
+
|
3
|
+
# Sets all the javascript needed for papermill.
|
4
|
+
# If you already loaded jQuery and JQueryUI, call papermill_javascript_tag
|
5
|
+
# If you don't use jQuery or use some other library, call papermill_javascript_tag(:with_jquery => "no_conflict")
|
6
|
+
# If you want to rely on this helper to load jQuery/jQueryUI and use it, call papermill_javascript_tag(:with_jquery => true)
|
7
|
+
# If you loaded jQuery and need to load only jQueryUI, call papermill_javascript_tag(:with_jqueryui_only => true)
|
8
|
+
# If you changed the location of papermill.js, you'll need to set :root_folder (defaults to "javascripts")
|
9
|
+
def papermill_javascript_tag(options = {})
|
10
|
+
html = []
|
11
|
+
root_folder = options[:path] || "javascripts"
|
12
|
+
if options[:with_jquery] || options[:with_jqueryui]
|
13
|
+
html << %{<script src="http://www.google.com/jsapi"></script>}
|
14
|
+
html << %{<script type="text/javascript">}
|
15
|
+
html << %{google.load("jquery", "1");} if options[:with_jquery]
|
16
|
+
html << %{google.load("jqueryui", "1");} if options[:with_jquery] || options[:with_jqueryui_only]
|
17
|
+
html << %{jQuery.noConflict();} if options[:with_jquery] == "no_conflict"
|
18
|
+
html << %{</script>}
|
19
|
+
end
|
20
|
+
html << %{<script src="http://swfupload.googlecode.com/svn/swfupload/tags/swfupload_v2.2.0_core/swfupload.js"></script>}
|
21
|
+
html << %{<script type="text/javascript">\n//<![CDATA[}
|
22
|
+
["SWFUPLOAD_PENDING", "SWFUPLOAD_LOADING", "SWFUPLOAD_ERROR"].each do |js_constant|
|
23
|
+
html << %{var #{js_constant} = "#{I18n.t(js_constant, :scope => "papermill")}";}
|
24
|
+
end
|
25
|
+
html << %{//]]>\n</script>}
|
26
|
+
html << javascript_include_tag("/#{root_folder}/papermill", :cache => "swfupload-papermill")
|
27
|
+
unless @content_for_papermill_inline_js.blank?
|
28
|
+
html << '<script type="text/javascript">jQuery(document).ready(function() {'
|
29
|
+
html << @content_for_papermill_inline_js
|
30
|
+
html << '});</script>'
|
31
|
+
end
|
32
|
+
html.join("\n")
|
33
|
+
end
|
34
|
+
|
35
|
+
# Sets the css tags needed for papermill.
|
36
|
+
# If you changed the location of papermill.css, you'll need to set :root_folder (defaults to "stylesheets")
|
37
|
+
def papermill_stylesheet_tag(options = {})
|
38
|
+
html = []
|
39
|
+
root_folder = options[:path] || "stylesheets"
|
40
|
+
html << stylesheet_link_tag("/#{root_folder}/papermill")
|
41
|
+
unless @content_for_papermill_inline_css.blank?
|
42
|
+
html << %{<style type="text/css">}
|
43
|
+
html << @content_for_papermill_inline_css
|
44
|
+
html << %{</style>}
|
45
|
+
end
|
46
|
+
html.join("\n")
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
module Papermill
|
2
|
+
|
3
|
+
# Override these defaults :
|
4
|
+
# - in your application (environment.rb, ..) => in your [environment, development, production].rb file with Papermill::OPTIONS = {thumbnails => {..}, :gallery => {..}, etc. }
|
5
|
+
# - in your class => papermill <assoc_name>, :class_name => MySTIedPapermillAssetSubClass, thumbnails => {<my_thumbnail_parameters>}, :gallery => {<my_gallery_parameters>}, etc.
|
6
|
+
# - in your helper call => images_upload :my_gallery, {thumbnails => {..}, :gallery => {..}, etc. }
|
7
|
+
# Options will cascade as you expect them to.
|
8
|
+
|
9
|
+
# sizes (widths, paddings, etc..) are CSS pixel values.
|
10
|
+
PAPERMILL_DEFAULTS = {
|
11
|
+
:thumbnail => {
|
12
|
+
# you clearly want to override these two values in your templates.
|
13
|
+
# the rest is very optionnal and will "cascade" nicely
|
14
|
+
:width => 100, # Recommended if :gallery[:width] is nil
|
15
|
+
:height => 100, # Recommended if :gallery[:height] is nil
|
16
|
+
# set :width OR :height to nil to use aspect_ratio value. Remember that 4/3 == 1 => Use : 4.0/3
|
17
|
+
:aspect_ratio => nil,
|
18
|
+
:max_width => 1000,
|
19
|
+
:max_height => 1000,
|
20
|
+
# You can override computed ImageMagick transformation strings that defaults to "#{:width}x#{:height}>"
|
21
|
+
# Note that this is required if PAPERMILL_DEFAULTS[:alias_only] is true
|
22
|
+
:style => nil,
|
23
|
+
# set to false if you don't want inline CSS
|
24
|
+
:inline_css => true
|
25
|
+
},
|
26
|
+
# gallery
|
27
|
+
:gallery => {
|
28
|
+
# if thumbnail.inline_css is true, css will be generated automagically with these values. Great for quick scaffolding, and complete enough for real use.
|
29
|
+
:width => nil, # overrides calculated width. Recommended if :thumbnail[:width] is nil.
|
30
|
+
:height => nil, # overrides calculated height. Recommended if :thumbnail[:height] is nil.
|
31
|
+
:columns => 8, # number of columns. If thumbnail.width has a value, sets a width for the gallery, calculated from thumbnails width multiplied by :columns.
|
32
|
+
:lines => 2, # number of default lines. (height will autogrow) If thumbnail.height has a value, sets a min-height for the gallery, calculated from thumbnails height multiplied by :lines
|
33
|
+
:vpadding => 0, # vertical padding around thumbnails
|
34
|
+
:hpadding => 0, # horizontal padding around thumbnails
|
35
|
+
:vmargin => 1, # vertical margin around thumbnails
|
36
|
+
:hmargin => 1, # horizontal margin around thumbnails
|
37
|
+
:border_thickness => 2, # border around thumbnails
|
38
|
+
:autogrow => false # sets a min-height instead of height for the gallery
|
39
|
+
},
|
40
|
+
# options passed on to SWFUpload. To remove an option when overriding, set it to nil.
|
41
|
+
:swfupload => {
|
42
|
+
# !!! Will only work if the swf file comes from the server to where the files are sent. (Flash same origin security policy)
|
43
|
+
:flash_url => '/flashs/swfupload.swf',
|
44
|
+
# You can use upload-blank.png with your own wording or upload.png with default "upload" wording (looks nicer)
|
45
|
+
:button_image_url => '/images/papermill/upload-blank.png',
|
46
|
+
:button_width => 61,
|
47
|
+
:button_height => 22,
|
48
|
+
# Wording and CSS processed through an Adobe Flash styler. Result is terrible. Feel free to put a CSS button overlayed directly on the SWF button. See swfupload website.
|
49
|
+
:button_text => %{<span class="button-text">#{I18n.t("upload-button-wording", :scope => :papermill)}</span>},
|
50
|
+
:button_text_style => %{.button-text { color: red; font-size: 12pt; font-weight: bold; }},
|
51
|
+
:button_disabled => "false",
|
52
|
+
:button_text_top_padding => 4,
|
53
|
+
:button_text_left_padding => 4,
|
54
|
+
:debug => "false",
|
55
|
+
:prevent_swf_caching => "false"
|
56
|
+
# See swfupload.js for details.
|
57
|
+
},
|
58
|
+
:images_only => false, # set to true to forbid upload of anything else than images
|
59
|
+
:file_size_limit_mb => 10, # file max size
|
60
|
+
:button_after_container => false, # set to true to move the upload button below the container
|
61
|
+
|
62
|
+
# DO NOT CHANGE THESE IN YOUR CLASSES. Only application wide (routes depend on it..)
|
63
|
+
:alias_only => false, # set to true so that only aliases are authorized in url/path
|
64
|
+
:aliases => {
|
65
|
+
# "example" => "100x100#",
|
66
|
+
},
|
67
|
+
# path to the root of your public directory
|
68
|
+
:public_root => ":rails_root/public",
|
69
|
+
# added to :public_root as the root folder for all papermill items
|
70
|
+
:papermill_prefix => "system/papermill"
|
71
|
+
}.deep_merge( Papermill.const_defined?("OPTIONS") ? Papermill::OPTIONS : {} )
|
72
|
+
|
73
|
+
PAPERCLIP_INTERPOLATION_STRING = ":id_partition/:style/:escaped_basename.:extension"
|
74
|
+
|
75
|
+
def self.included(base)
|
76
|
+
base.extend(ClassMethods)
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.papermill_interpolated_path(replacements_pairs, up_to)
|
80
|
+
replacements_pairs = {"other" => "*", ":rails_root" => RAILS_ROOT}.merge(replacements_pairs)
|
81
|
+
a = "#{PAPERMILL_DEFAULTS[:public_root]}/#{PAPERMILL_DEFAULTS[:papermill_prefix]}/#{PAPERCLIP_INTERPOLATION_STRING}".split("/")
|
82
|
+
"#{a[0..(up_to && a.index(up_to) || -1)].map{ |s| s.starts_with?(':') ? (replacements_pairs[s] || replacements_pairs['other'] || s) : s }.join('/')}"
|
83
|
+
end
|
84
|
+
|
85
|
+
module ClassMethods
|
86
|
+
attr_reader :papermill_associations
|
87
|
+
|
88
|
+
# papermill comes in 2 flavors:
|
89
|
+
#
|
90
|
+
# 1. generic declaration =>
|
91
|
+
# declare associations with => papermill {my_option_hash}
|
92
|
+
# create assets with => assets_upload(:my_key, {optional_option_hash})
|
93
|
+
# access assets with => assetable.papermill_assets(:key => :my_key)
|
94
|
+
#
|
95
|
+
# 2. association declaration =>
|
96
|
+
# declare associations with => papermill :my_association, {my_option_hash}
|
97
|
+
# create assets with => assets_upload(my_association, {optional_option_hash})
|
98
|
+
# access assets with => assetable.my_association
|
99
|
+
#
|
100
|
+
# In both case, you can specify a PapermillAsset subclass to use with :class_name => MyPapermillAssetSubclass in the option hash
|
101
|
+
def papermill(assoc_name = :papermill_assets, options = {})
|
102
|
+
if assoc_name.is_a? Hash
|
103
|
+
options = assoc_name
|
104
|
+
assoc_name = :papermill_assets
|
105
|
+
end
|
106
|
+
|
107
|
+
@papermill_associations ||= {}
|
108
|
+
begin
|
109
|
+
class_name = options.delete(:class_name)
|
110
|
+
asset_class = class_name && class_name.to_s.constantize || PapermillAsset
|
111
|
+
rescue
|
112
|
+
raise Exception.new("Papermill: can't find class #{class_name.to_s}.\n#{class_name.to_s} should be a subclass of PapermillAsset")
|
113
|
+
end
|
114
|
+
|
115
|
+
@papermill_associations.merge!({assoc_name => {:class => asset_class, :options => Papermill::PAPERMILL_DEFAULTS.deep_merge(options)}})
|
116
|
+
before_destroy :destroy_assets
|
117
|
+
after_create :rebase_assets
|
118
|
+
|
119
|
+
define_method assoc_name do |*options|
|
120
|
+
klass = self.class.papermill_associations[assoc_name.to_sym][:class]
|
121
|
+
options = options.first || {}
|
122
|
+
if (options.is_a?(Symbol) || options.is_a?(String))
|
123
|
+
key = options
|
124
|
+
options = {}
|
125
|
+
else
|
126
|
+
key = nil
|
127
|
+
end
|
128
|
+
conditions = {
|
129
|
+
:assetable_type => self.class.sti_name,
|
130
|
+
:assetable_id => self.id
|
131
|
+
}.merge(options.delete(:conditions) || {})
|
132
|
+
key ||= (assoc_name != :papermill_assets) && assoc_name.to_s
|
133
|
+
conditions.merge!({:assetable_key => key.to_s}) if key
|
134
|
+
|
135
|
+
hash = {
|
136
|
+
:conditions => conditions,
|
137
|
+
:order => options.delete(:order) || "position ASC"
|
138
|
+
}.merge(options)
|
139
|
+
asset_class.find(:all, hash)
|
140
|
+
end
|
141
|
+
|
142
|
+
class_eval <<-EOV
|
143
|
+
include Papermill::InstanceMethods
|
144
|
+
EOV
|
145
|
+
end
|
146
|
+
|
147
|
+
def inherited(subclass)
|
148
|
+
subclass.instance_variable_set("@papermill_associations", @papermill_associations)
|
149
|
+
super
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
module InstanceMethods
|
154
|
+
attr_writer :timestamp
|
155
|
+
def timestamp
|
156
|
+
@timestamp ||= "-#{(Time.now.to_f * 1000).to_i.to_s[4..-1]}"
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def destroy_assets
|
162
|
+
PapermillAsset.find(:all, :conditions => {:assetable_id => self.id, :assetable_type => self.class.sti_name}).each do |asset|
|
163
|
+
asset.destroy
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def rebase_assets
|
168
|
+
PapermillAsset.find(:all, :conditions => {:assetable_id => self.timestamp, :assetable_type => self.class.sti_name}).each do |asset|
|
169
|
+
if asset.created_at < 2.hours.ago
|
170
|
+
asset.destroy
|
171
|
+
else
|
172
|
+
asset.update_attribute(:assetable_id, self.id)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
data/papermill.gemspec
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{papermill}
|
8
|
+
s.version = "0.5.7"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Benoit B\303\251n\303\251zech"]
|
12
|
+
s.date = %q{2009-09-08}
|
13
|
+
s.description = %q{Paperclip Swfupload UploadHelper wrapper}
|
14
|
+
s.email = %q{benoit.benezech@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"MIT-LICENSE",
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"app/controllers/papermill_controller.rb",
|
25
|
+
"app/views/papermill/_asset.html.erb",
|
26
|
+
"app/views/papermill/_raw_asset.html.erb",
|
27
|
+
"app/views/papermill/_thumbnail_asset.html.erb",
|
28
|
+
"app/views/papermill/edit.html.erb",
|
29
|
+
"config/locales/papermill.yml",
|
30
|
+
"config/routes.rb",
|
31
|
+
"generators/papermill/USAGE",
|
32
|
+
"generators/papermill/papermill_generator.rb",
|
33
|
+
"generators/papermill/templates/migrate/papermill_migration.rb.erb",
|
34
|
+
"init.rb",
|
35
|
+
"install.rb",
|
36
|
+
"installation-template.txt",
|
37
|
+
"lib/core_extensions.rb",
|
38
|
+
"lib/papermill.rb",
|
39
|
+
"lib/papermill/form_builder.rb",
|
40
|
+
"lib/papermill/papermill_asset.rb",
|
41
|
+
"lib/papermill/papermill_helper.rb",
|
42
|
+
"lib/papermill/papermill_module.rb",
|
43
|
+
"papermill.gemspec",
|
44
|
+
"public/.DS_Store",
|
45
|
+
"public/flashs/swfupload.swf",
|
46
|
+
"public/images/.DS_Store",
|
47
|
+
"public/images/papermill/.DS_Store",
|
48
|
+
"public/images/papermill/background.png",
|
49
|
+
"public/images/papermill/container-background.jpg",
|
50
|
+
"public/images/papermill/delete.png",
|
51
|
+
"public/images/papermill/upload-blank.png",
|
52
|
+
"public/images/papermill/upload.png",
|
53
|
+
"public/javascripts/papermill.js",
|
54
|
+
"public/stylesheets/papermill.css",
|
55
|
+
"rails/init.rb",
|
56
|
+
"tasks/papermill_tasks.rake",
|
57
|
+
"test/papermill_test.rb",
|
58
|
+
"test/test_helper.rb",
|
59
|
+
"uninstall.rb"
|
60
|
+
]
|
61
|
+
s.homepage = %q{http://github.com/BBenezech/papermill}
|
62
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
63
|
+
s.require_paths = ["lib"]
|
64
|
+
s.rubyforge_project = %q{papermill}
|
65
|
+
s.rubygems_version = %q{1.3.5}
|
66
|
+
s.summary = %q{Paperclip Swfupload UploadHelper wrapper}
|
67
|
+
s.test_files = [
|
68
|
+
"test/papermill_test.rb",
|
69
|
+
"test/test_helper.rb"
|
70
|
+
]
|
71
|
+
|
72
|
+
if s.respond_to? :specification_version then
|
73
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
74
|
+
s.specification_version = 3
|
75
|
+
|
76
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
77
|
+
s.add_runtime_dependency(%q<paperclip>, [">= 2.1.2"])
|
78
|
+
s.add_runtime_dependency(%q<mime-types>, [">= 1.16"])
|
79
|
+
s.add_runtime_dependency(%q<rsl-stringex>, [">= 1.0.0"])
|
80
|
+
s.add_runtime_dependency(%q<ryanb-acts-as-list>, [">= 0.1.2"])
|
81
|
+
else
|
82
|
+
s.add_dependency(%q<paperclip>, [">= 2.1.2"])
|
83
|
+
s.add_dependency(%q<mime-types>, [">= 1.16"])
|
84
|
+
s.add_dependency(%q<rsl-stringex>, [">= 1.0.0"])
|
85
|
+
s.add_dependency(%q<ryanb-acts-as-list>, [">= 0.1.2"])
|
86
|
+
end
|
87
|
+
else
|
88
|
+
s.add_dependency(%q<paperclip>, [">= 2.1.2"])
|
89
|
+
s.add_dependency(%q<mime-types>, [">= 1.16"])
|
90
|
+
s.add_dependency(%q<rsl-stringex>, [">= 1.0.0"])
|
91
|
+
s.add_dependency(%q<ryanb-acts-as-list>, [">= 0.1.2"])
|
92
|
+
end
|
93
|
+
end
|