BBenezech-papermill 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/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .DS_Store
2
+ log/*.log
3
+ tmp/**/*
4
+ config/database.yml
5
+ db/*.sqlite3
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 [name of plugin creator]
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,62 @@
1
+ = Papermill
2
+
3
+ Asset management made easy.. Painfully easy.
4
+ Try the demo to see for yourself.
5
+
6
+ See papermill_module.rb for a complete list of available options.
7
+ These options can be application wide, for a class, or set at the last moment for the helper.
8
+
9
+ In your model:
10
+
11
+ papermill :assets
12
+
13
+ In your layout:
14
+
15
+ <%= papermill_stylesheet_tag %>
16
+ <%= papermill_javascript_tag :with_jquery => true %>
17
+
18
+ In your edit form:
19
+
20
+ f.images_upload(:my_image_gallery)
21
+ f.image_upload(:header_image)
22
+
23
+ Finally, in your views:
24
+
25
+ # Some template image :
26
+ <%= image_tag @article.assets(:header_image).first.url("800x>") %>
27
+
28
+ # Some image gallery:
29
+ <ul>
30
+ <% @article.assets(:my_image_gallery).each do |image| %>
31
+ <li><%= link_to(image_tag(image.url("100x100>")), image.url) %></li>
32
+ <% end %>
33
+ </ul>
34
+
35
+ Also see http://gist.github.com/177714.txt to get up-to-date installation steps.
36
+ See the API here http://rdoc.info/projects/BBenezech/papermill
37
+
38
+ == Word of caution:
39
+
40
+ Beta.
41
+
42
+ This is xNIX only (system("rm ...")).
43
+
44
+ You'll need rails 2.3, since this is an engine. Anyway, copying the controller/view/routes to your project will make it work on an older version of rails.
45
+
46
+ You'll need rails 2.2, since their are calls to I18n.t. But it shouldn't be too hard to work-around either.
47
+
48
+ == Usage :
49
+
50
+ === Demo :
51
+
52
+ You can use the custom template generator to get an example application up and running in no time.
53
+
54
+ rails -m http://gist.github.com/177714.txt papermill-example
55
+
56
+ === Translation:
57
+
58
+ Papermill is fully Rails 2.2 I18n-able.
59
+
60
+ Copy config/locale/papermill.yml to your root config/locale folder to modify any wording in a any locale.
61
+
62
+ Copyright (c) 2009 Benoit Bénézech, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,37 @@
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 papermill plugin.'
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 papermill plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'Papermill'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
24
+
25
+ begin
26
+ require 'jeweler'
27
+ Jeweler::Tasks.new do |gemspec|
28
+ gemspec.name = "papermill"
29
+ gemspec.summary = "Paperclip wrapper"
30
+ gemspec.description = "Paperclip wrapper"
31
+ gemspec.email = "benoit.benezech@gmail.com"
32
+ gemspec.homepage = "http://github.com/BBenezech/papermill"
33
+ gemspec.authors = ["Benoit Bénézech"]
34
+ end
35
+ rescue LoadError
36
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
37
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,80 @@
1
+ class PapermillController < ApplicationController
2
+
3
+ skip_before_filter :verify_authenticity_token
4
+
5
+ def show
6
+ begin
7
+ if Papermill::PAPERMILL_DEFAULTS[:alias_only]
8
+ style = Papermill::PAPERMILL_DEFAULTS[:aliases][params[:style]]
9
+ else
10
+ style = Papermill::PAPERMILL_DEFAULTS[:aliases][params[:style]] || params[:style]
11
+ end
12
+ raise unless style
13
+ asset = PapermillAsset.find(params[:id])
14
+ temp_thumbnail = Paperclip::Thumbnail.make(asset_file = asset.file, style)
15
+ new_parent_folder_path = File.dirname(new_image_path = asset_file.path(params[:style]))
16
+ FileUtils.mkdir_p new_parent_folder_path unless File.exists? new_parent_folder_path
17
+ FileUtils.cp temp_thumbnail.path, new_image_path
18
+ redirect_to asset.url(params[:style])
19
+ rescue
20
+ render :text => t("not-processed", :scope => "papermill"), :status => "500"
21
+ end
22
+ end
23
+
24
+ def destroy
25
+ begin
26
+ @asset = PapermillAsset.find(params[:id])
27
+ render :update do |page|
28
+ if @asset.destroy
29
+ page << "jQuery('#papermill_asset_#{params[:id]}').remove()"
30
+ else
31
+ page << "jQuery('#papermill_asset_#{params[:id]}').show()"
32
+ message = t("not-deleted", :ressource => @asset.name, :scope => "papermill")
33
+ page << %{ notify("#{message}", error) }
34
+ end
35
+ end
36
+ rescue ActiveRecord::RecordNotFound
37
+ render :update do |page|
38
+ page << "jQuery('#papermill_asset_#{params[:id]}').remove()"
39
+ message = t("not-found", :ressource => params[:id].to_s, :scope => "papermill")
40
+ page << %{ notify("#{message}", "warning") }
41
+ end
42
+ end
43
+ end
44
+
45
+ def update
46
+ @asset = PapermillAsset.find params[:id]
47
+ @asset.update(params)
48
+ render :update do |page|
49
+ message = t("updated", :ressource => @asset.name, :scope => "papermill")
50
+ page << %{ notify("#{message}", "notice") }
51
+ end
52
+ end
53
+
54
+ def edit
55
+ @asset = PapermillAsset.find params[:id]
56
+ end
57
+
58
+ def create
59
+ params[:assetable_type] = params[:assetable_type].camelize
60
+ asset_class = params[:assetable_type].constantize.papermill_associations[params[:association].to_sym][:class]
61
+ params[:swfupload_file] = params.delete(:Filedata)
62
+ @old_asset = asset_class.find(:first, :conditions => {:assetable_key => params[:assetable_key].to_s, :assetable_type => params[:assetable_type], :assetable_id => params[:assetable_id]}) unless params[:gallery]
63
+ @asset = asset_class.new(params.reject{|key, value| !(PapermillAsset.columns.map(&:name)+["swfupload_file"]).include?(key.to_s)})
64
+
65
+ if @asset.save
66
+ @old_asset.destroy if @old_asset
67
+ render :partial => "papermill/asset", :object => @asset, :locals => {:thumbnail => params[:thumbnail], :gallery => params[:gallery], :thumbnail_style => params[:thumbnail_style]}
68
+ else
69
+ message = t("not-created", :scope => "papermill")
70
+ render :text => message, :status => "500"
71
+ end
72
+ end
73
+
74
+ def sort
75
+ params[:papermill_asset].each_with_index do |id, index|
76
+ PapermillAsset.find(id).update_attribute(:position, index + 1)
77
+ end
78
+ render :nothing => true
79
+ end
80
+ end
@@ -0,0 +1,11 @@
1
+ <%- dom_id = dom_id(asset) -%>
2
+ <%- delete_link = %{<a onclick="if(confirm('#{escape_javascript I18n.t("delete-confirmation", :scope => :papermill, :resource => asset.name)}')){ $.ajax({async:true, beforeSend:function(request){$('##{dom_id}').hide();}, dataType:'script', error:function(request){$('##{dom_id}').show();}, type:'delete', url:'#{papermill_url(asset)}'})}; return false;" href="#" class="delete"><img title="#{escape_javascript t("delete", :scope => "papermill", :ressource => asset.name)}" src="/images/papermill/delete.png" alt="delete"/></a>} %>
3
+
4
+ <li id="<%= dom_id %>" rel="<%= edit_papermill_url(asset) %>" title="<%= t("#{thumbnail_style ? "thumbnail-" : ""}edit-title", :scope => "papermill", :ressource => asset.name) %>">
5
+ <%= delete_link %>
6
+ <%- if thumbnail_style -%>
7
+ <%= render :partial => "papermill/thumbnail_asset", :object => asset, :locals => {:thumbnail_style => thumbnail_style} %>
8
+ <%- else -%>
9
+ <%= render :partial => "papermill/raw_asset", :object => asset %>
10
+ <%- end -%>
11
+ </li>
@@ -0,0 +1 @@
1
+ <%= link_to(raw_asset.name, raw_asset.url, :class => "name") -%>
@@ -0,0 +1,6 @@
1
+ <% if thumbnail_asset.image? %>
2
+ <span class="image"><%= image_tag(thumbnail_asset.url(thumbnail_style)) %></span>
3
+ <% else %>
4
+ <span class="name" title="<%= thumbnail_asset.name %>"><%= truncate(thumbnail_asset.name, :length => 15) %></span>
5
+ <span class="infos"><%= thumbnail_asset.content_type[1] %></span>
6
+ <% end %>
@@ -0,0 +1,30 @@
1
+ en:
2
+ papermill:
3
+ not-processed: "Error/ressource not processed"
4
+ updated: "{{ressource}} updated"
5
+ not-deleted: "{{ressource}} could not be deleted"
6
+ not-created: "Ressource could not be created"
7
+ not-found: "Asset #{{ressource}} not found"
8
+ edit-title: "" # You can use {{ressource}}
9
+ thumbnail-edit-title: ""
10
+ upload-button-wording: "Upload..."
11
+ delete: "Remove {{ressource}}"
12
+ delete-confirmation: "Delete '{{resource}}'?"
13
+ SWFUPLOAD_PENDING: "Pending..."
14
+ SWFUPLOAD_LOADING: "Loading..."
15
+ SWFUPLOAD_ERROR: "Something happened while loading" # + " <file_name> (<swfupload error message> [<error code>])"
16
+ fr:
17
+ papermill:
18
+ not-processed: "Erreur/ressource non trouvée"
19
+ updated: "{{ressource}} mise à jour"
20
+ not-deleted: "{{ressource}} n'a pas pu être supprimée"
21
+ not-created: "La ressource n'a pas pu être créée"
22
+ not-found: "Asset #{{ressource}} non trouvé"
23
+ edit-title: ""
24
+ thumbnail-edit-title: ""
25
+ upload-button-wording: "Charger.."
26
+ delete: "Supprimer {{ressource}}"
27
+ delete-confirmation: "Êtes-vous sûr de vouloir supprimer '{{resource}}' ?"
28
+ SWFUPLOAD_PENDING: "En attente..."
29
+ SWFUPLOAD_LOADING: "Chargement..."
30
+ SWFUPLOAD_ERROR: "Une erreur est survenue pendant le chargement de"
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.resources :papermill, :collection => { :sort => :post }
3
+ map.connect "#{Papermill::PAPERMILL_DEFAULTS[:papermill_prefix]}/#{Papermill::PAPERCLIP_INTERPOLATION_STRING}", :controller => "papermill", :action => "show"
4
+ end
@@ -0,0 +1,3 @@
1
+ script/generate papermill MyTableName
2
+
3
+ This will create the migration table.
@@ -0,0 +1,16 @@
1
+ class PapermillGenerator < Rails::Generator::NamedBase
2
+ attr_accessor :class_name, :migration_name
3
+
4
+ def initialize(args, options = {})
5
+ super
6
+ @class_name = args[0]
7
+ end
8
+
9
+ def manifest
10
+ @migration_name = file_name.camelize
11
+ record do |m|
12
+ # Migration creation
13
+ m.migration_template "migrate/papermill_migration.rb.erb", "db/migrate", :migration_file_name => migration_name.underscore
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ class <%= migration_name %> < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :papermill_assets do |t|
4
+ t.string :file_file_name
5
+ t.string :file_content_type
6
+ t.integer :file_file_size
7
+ t.integer :position
8
+ t.text :description
9
+ t.string :copyright
10
+ t.string :title
11
+ t.integer :assetable_id
12
+ t.string :assetable_type
13
+ t.string :assetable_key
14
+ t.string :type
15
+ t.timestamps
16
+ end
17
+ end
18
+
19
+ def self.down
20
+ drop_table :papermill_assets
21
+ end
22
+ end
data/init.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'core_extensions'
2
+ Object.send :include, ObjectExtensions
3
+ Hash.send :include, HashExtensions
4
+ String.send :include, StringExtensions
5
+
6
+ I18n.load_path = [File.join(File.dirname(__FILE__), 'config/locale/papermill.yml')] + I18n.load_path
7
+
8
+ require 'papermill'
9
+ ActionView::Base.send :include, PapermillHelper
10
+ ActiveRecord::Base.send :include, Papermill
data/install.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "fileutils"
2
+
3
+ FileUtils.cp_r(
4
+ Dir[File.join(File.dirname(__FILE__), 'public')],
5
+ File.join(RAILS_ROOT),
6
+ :verbose => true
7
+ )
@@ -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
@@ -0,0 +1,4 @@
1
+ require 'papermill/papermill_module'
2
+ require 'papermill/papermill_asset'
3
+ require 'papermill/form_builder'
4
+ require 'papermill/papermill_helper'
@@ -0,0 +1,91 @@
1
+ class ActionView::Helpers::FormBuilder
2
+
3
+ def assets_upload(key = nil, method = nil, options = {})
4
+ papermill_upload_field key, method, { :thumbnail => false }.update(options)
5
+ end
6
+ def asset_upload(key = nil, method = nil, options = {})
7
+ papermill_upload_field key, method, { :gallery => false, :thumbnail => false }.update(options)
8
+ end
9
+ def images_upload(key = nil, method = nil, options = {})
10
+ papermill_upload_field key, method, options
11
+ end
12
+ def image_upload(key = nil, method = nil, options = {})
13
+ papermill_upload_field key, method, { :gallery => false }.update(options)
14
+ end
15
+
16
+ private
17
+ def papermill_upload_field(key, method, options = {})
18
+ assetable = @template.instance_variable_get("@#{@object_name}")
19
+ method ||= options[:association] || :papermill_assets
20
+ key ||= options[:key] || nil
21
+ options = assetable.class.papermill_options.deep_merge(options)
22
+ assetable_id = assetable.id || assetable.timestamp
23
+ assetable_type = assetable.class.to_s.underscore
24
+ id = "papermill_#{assetable_type}_#{assetable_id}_#{key}_#{method}"
25
+ if options[:thumbnail]
26
+ w = options[:thumbnail][:width] || options[:thumbnail][:height] && options[:thumbnail][:aspect_ratio] && (options[:thumbnail][:height] * options[:thumbnail][:aspect_ratio]).to_i || nil
27
+ h = options[:thumbnail][:height] || options[:thumbnail][:width] && options[:thumbnail][:aspect_ratio] && (options[:thumbnail][:width] / options[:thumbnail][:aspect_ratio]).to_i || nil
28
+ options[:thumbnail][:style] ||= (w || h) && "#{w || options[:thumbnail][:max_width]}x#{h || options[:thumbnail][:max_height]}>" || "original"
29
+ if options[:thumbnail][:inline_css]
30
+ size = []
31
+ size << "width:#{w}px" if w
32
+ size << "height:#{h}px" if h
33
+ size = size.join("; ")
34
+ @template.content_for :inline_css do
35
+ inline_css = ["\n"]
36
+ if options[:gallery]
37
+ vp = options[:gallery][:vpadding].to_i
38
+ hp = options[:gallery][:hpadding].to_i
39
+ vm = options[:gallery][:vmargin].to_i
40
+ hm = options[:gallery][:hmargin].to_i
41
+ b = options[:gallery][:border_thickness].to_i
42
+ gallery_width = (options[:gallery][:width] || w) && "width:#{options[:gallery][:width] || options[:gallery][:columns]*(w+(hp+hm+b)*2)}px;" || ""
43
+ gallery_height = (options[:gallery][:height] || h) && "#{options[:gallery][:autogrow] ? "" : "min-"}height:#{options[:gallery][:height] || options[:gallery][:lines]*(h+(vp+vm+b)*2)}px;" || ""
44
+ inline_css << %{##{id} { #{gallery_width} #{gallery_height} }}
45
+ inline_css << %{##{id} li { margin:#{vm}px #{hm}px; border-width:#{b}px; padding:#{vp}px #{hp}px; #{size}; }}
46
+ else
47
+ inline_css << %{##{id}, ##{id} li { #{size} }}
48
+ end
49
+ inline_css << %{##{id} .name { width:#{w || "100"}px; }}
50
+ inline_css.join("\n")
51
+ end
52
+ end
53
+ end
54
+ create_url = @template.url_for(:controller => "/papermill", :action => "create", :escape => false, :association => method.to_s, :assetable_key => key, :assetable_id => assetable_id, :assetable_type => assetable_type, :gallery => (options[:gallery] != false), :thumbnail_style => (options[:thumbnail] && options[:thumbnail][:style]))
55
+ html = []
56
+ if assetable.new_record? && !@timestamped
57
+ html << self.hidden_field(:timestamp, :value => assetable.timestamp)
58
+ @timestamped = true
59
+ end
60
+ html << %{<div style="height: #{options[:swfupload][:button_height]}px;"><span id="browse_for_#{id}" class="swf_button"></span></div>}
61
+ conditions = {:assetable_type => assetable.class.sti_name, :assetable_id => assetable_id}
62
+ conditions.merge!({:assetable_key => key.to_s}) if key
63
+ 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")}") {
64
+ @template.render :partial => "papermill/asset", :collection => assetable.class.papermill_associations[method][:class].find(:all, :conditions => conditions, :order => "position"), :locals => { :thumbnail_style => (options[:thumbnail] && options[:thumbnail][:style]) }
65
+ }
66
+ @template.content_for :inline_js do
67
+ %{
68
+ #{%{$("##{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]}
69
+ new SWFUpload({
70
+ upload_id: "#{id}",
71
+ upload_url: "#{@template.escape_javascript create_url}",
72
+ file_size_limit: "#{options[:file_size_limit_mb].megabytes}",
73
+ file_types: "#{options[:images_only] ? '*.jpg;*.jpeg;*.png;*.gif' : ''}",
74
+ file_types_description: "#{options[:thumbnail] ? 'Images' : 'Files'}",
75
+ file_queue_limit: "#{!options[:gallery] ? '1' : '0'}",
76
+ file_queued_handler: Upload.file_queued,
77
+ file_dialog_complete_handler: Upload.file_dialog_complete,
78
+ upload_start_handler: Upload.upload_start,
79
+ upload_progress_handler: Upload.upload_progress,
80
+ upload_error_handler: Upload.upload_error,
81
+ upload_success_handler: Upload.upload_success,
82
+ upload_complete_handler: Upload.upload_complete,
83
+ button_placeholder_id : "browse_for_#{id}",
84
+ #{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(", ")}
85
+ });
86
+ }
87
+ end
88
+ html.reverse! if options[:button_after_container]
89
+ html.join("\n")
90
+ end
91
+ end
@@ -0,0 +1,67 @@
1
+ class PapermillAsset < ActiveRecord::Base
2
+ acts_as_list :scope => 'assetable_key=\'#{assetable_key.simple_sql_sanitizer}\' AND assetable_id=#{assetable_id} AND assetable_type=\'#{assetable_type}\''
3
+
4
+ belongs_to :assetable, :polymorphic => true
5
+ before_destroy :destroy_files
6
+
7
+ named_scope :key, lambda { |key| { :conditions => { :assetable_key => key } } }
8
+
9
+ Paperclip::Attachment.interpolations[:assetable_type] = proc do |attachment, style|
10
+ attachment.instance.assetable_type.underscore.pluralize
11
+ end
12
+
13
+ Paperclip::Attachment.interpolations[:assetable_id] = proc do |attachment, style|
14
+ attachment.instance.assetable_id
15
+ end
16
+
17
+ Paperclip::Attachment.interpolations[:assetable_key] = proc do |attachment, style|
18
+ attachment.instance.assetable_key.to_url
19
+ end
20
+
21
+ Paperclip::Attachment.interpolations[:escaped_basename] = proc do |attachment, style|
22
+ Paperclip::Attachment.interpolations[:basename].call(attachment, style).to_url
23
+ end
24
+
25
+ has_attached_file :file,
26
+ :path => "#{Papermill::PAPERMILL_DEFAULTS[:public_root]}/#{Papermill::PAPERMILL_DEFAULTS[:papermill_prefix]}/#{Papermill::PAPERCLIP_INTERPOLATION_STRING}",
27
+ :url => "/#{Papermill::PAPERMILL_DEFAULTS[:papermill_prefix]}/#{Papermill::PAPERCLIP_INTERPOLATION_STRING}"
28
+ validates_attachment_presence :file
29
+
30
+ #validates_attachment_content_type :file, :content_type => ['image/jpeg', 'image/pjpeg', 'image/jpg', 'image/png', 'image/gif']
31
+
32
+ # Fix the mime types. Make sure to require the mime-types gem
33
+ def swfupload_file=(data)
34
+ data.content_type = MIME::Types.type_for(data.original_filename).to_s
35
+ self.file = data
36
+ end
37
+
38
+ def name
39
+ file_file_name
40
+ end
41
+
42
+ def size
43
+ file_file_size
44
+ end
45
+
46
+ def url(style = nil)
47
+ file.url(style && CGI::escape(style.to_s))
48
+ end
49
+
50
+ def content_type
51
+ file_content_type.split("/") if file_content_type
52
+ end
53
+
54
+ def image?
55
+ content_type.first == "image" && content_type[1]
56
+ end
57
+
58
+ def interpolated_path(with = {}, up_to = nil)
59
+ Papermill::papermill_interpolated_path({":id" => self.id, ":assetable_id" => self.assetable_id, ":assetable_type" => self.assetable_type.underscore.pluralize}.merge(with), up_to)
60
+ end
61
+
62
+ # before_filter
63
+ def destroy_files
64
+ system "rm -rf #{self.interpolated_path({}, ':id')}/" if image?
65
+ true
66
+ end
67
+ end
@@ -0,0 +1,35 @@
1
+ module PapermillHelper
2
+
3
+ def papermill_javascript_tag(options = {})
4
+ html = []
5
+ root_folder = options[:path] || "javascripts"
6
+ if options[:with_jquery] || options[:with_jqueryui]
7
+ html << %{<script src="http://www.google.com/jsapi"></script>}
8
+ html << %{<script type="text/javascript">\n//<![CDATA[}
9
+ html << %{google.load("jquery", "1");} if options[:with_jquery]
10
+ html << %{google.load("jqueryui", "1");} if options[:with_jquery] || options[:with_jqueryui]
11
+ html << %{</script>}
12
+ end
13
+ html << %{<script src="http://swfupload.googlecode.com/svn/swfupload/tags/swfupload_v2.2.0_core/swfupload.js"></script>}
14
+ html << %{<script type="text/javascript">\n//<![CDATA[}
15
+ ["SWFUPLOAD_PENDING", "SWFUPLOAD_LOADING", "SWFUPLOAD_ERROR"].each do |js_constant|
16
+ html << %{var #{js_constant} = "#{I18n.t(js_constant, :scope => "papermill")}";}
17
+ end
18
+ html << %{//]]>\n</script>}
19
+ html << javascript_include_tag("/#{root_folder}/papermill", :cache => "swfupload-papermill")
20
+ html << '<script type="text/javascript">jQuery(document).ready(function() {'
21
+ html << @content_for_inline_js
22
+ html << '});</script>'
23
+ html.join("\n")
24
+ end
25
+
26
+ def papermill_stylesheet_tag(options = {})
27
+ html = []
28
+ root_folder = options[:path] || "stylesheets"
29
+ html << stylesheet_link_tag("/#{root_folder}/papermill")
30
+ html << %{<style type="text/css">}
31
+ html << @content_for_inline_css
32
+ html << %{</style>}
33
+ html.join("\n")
34
+ end
35
+ end
@@ -0,0 +1,182 @@
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 => "papermill"
71
+ }.deep_merge( Papermill.const_defined?("OPTIONS") ? Papermill::OPTIONS : {} )
72
+
73
+
74
+ PAPERCLIP_INTERPOLATION_STRING = ":assetable_type/:assetable_id/:id/:style/:escaped_basename.:extension"
75
+
76
+ def self.included(base)
77
+ base.extend(ClassMethods)
78
+ end
79
+
80
+ def self.papermill_interpolated_path(replacements_pairs, up_to)
81
+ replacements_pairs = {"other" => "*", ":rails_root" => RAILS_ROOT}.merge(replacements_pairs)
82
+ a = "#{PAPERMILL_DEFAULTS[:public_root]}/#{PAPERMILL_DEFAULTS[:papermill_prefix]}/#{PAPERCLIP_INTERPOLATION_STRING}".split("/")
83
+ "#{a[0..(up_to && a.index(up_to) || -1)].map{ |s| s.starts_with?(':') ? (replacements_pairs[s] || replacements_pairs['other'] || s) : s }.join('/')}"
84
+ end
85
+
86
+ module ClassMethods
87
+ attr_reader :papermill_options
88
+ attr_reader :papermill_associations
89
+
90
+ # Dealing with STIed Asset table in papermill declaration is dead easy, since papermill follows ActiveRecord :has_many global syntax and the Convention over configuration concept :
91
+ # papermill <association_name>, :class_name => MySTIedPapermillAssetClassName
92
+ # class MyAsset < PapermillAsset
93
+ # ...
94
+ # end
95
+ # class MyAssetableClass < ActiveRecord::Base
96
+ # 1 -> papermill :my_association, :class_name => MyAsset
97
+ # 2 -> papermill :class_name => MyAsset
98
+ # 3 -> papermill :my_assets
99
+ # 4 -> papermill :my_other_assets
100
+ # 5 -> papermill
101
+ # end
102
+ # assetable = MyAssetableClass.new
103
+ # 1 -> assetable.my_association attached MyAsset objects (no magic here, association and class_name both specified)
104
+ # 2 -> assetable.my_assets attached MyAsset objects (association infered from :class_name as expected)
105
+ # 3 -> assetable.my_assets attached MyAsset objects (class_name guessed from association name)
106
+ # 4 -> assetable.my_other_assets attached PapermillAssets objects (couldn't find MyOtherAsset class or MyOtherAsset is not a PapermillAsset subclass, use default PapermillAsset superclass)
107
+ # 5 -> assetable.papermill_assets attached PapermillAssets objects (defaults)
108
+
109
+ def papermill(assoc = nil, options = {})
110
+ @papermill_associations ||= {}
111
+ asset_class = ((klass = options.delete(:class_name)) && (klass = (klass.to_s.singularize.camelize.constantize rescue nil)) && klass.superclass == PapermillAsset && klass || assoc && (klass = (assoc.to_s.singularize.camelize.constantize rescue nil)) && klass.superclass == PapermillAsset && klass || PapermillAsset)
112
+ assoc ||= asset_class.to_s.pluralize.underscore.to_sym
113
+
114
+ @papermill_associations.merge!({assoc => {:class => asset_class}})
115
+ @papermill_options = Papermill::PAPERMILL_DEFAULTS.deep_merge(options)
116
+ association_finder = assoc.to_s + "_finder"
117
+ # using finder_sql because ActiveRecord chokes with STI on polymorphic tables. (Stupidely uses class.to_s instead of class.sti_name in association, god knows when it will get fixed, but tickets seems on the way for rails 3.0)
118
+ has_many association_finder, :finder_sql => 'SELECT * FROM papermill_assets WHERE papermill_assets.assetable_id = #{id} AND papermill_assets.assetable_type = "#{self.class.sti_name}" AND papermill_assets.type ' + (asset_class == PapermillAsset ? "IS NULL" : %{= "#{asset_class.to_s}"}) + ' ORDER BY papermill_assets.position'
119
+ after_create :rebase_assets
120
+ # reinventing the wheel because ActiveRecord chokes on :finder_sql with associations
121
+ # TODO Clean the mess
122
+ define_method assoc do |*options|
123
+ klass = self.class.papermill_associations[assoc.to_sym][:class]
124
+ options = options.first || {}
125
+ conditions = {
126
+ :assetable_type => self.class.sti_name,
127
+ :assetable_id => self.id,
128
+ }.merge(options.delete(:conditions) || {})
129
+ order = (options.delete(:order) || "position ASC")
130
+ conditions.merge!({:type => klass.to_s}) unless klass == PapermillAsset
131
+ conditions.merge!({:assetable_key => options[:key].to_s}) if options[:key]
132
+ conditions.merge!({:type => options[:class_name]}) if options[:class_name]
133
+ asset_class.find(:all, :conditions => conditions, :order => order)
134
+ end
135
+
136
+ after_destroy :remove_papermill_folder
137
+ class_eval <<-EOV
138
+ include Papermill::InstanceMethods
139
+ EOV
140
+ end
141
+
142
+ def inherited(subclass)
143
+ subclass.instance_variable_set("@papermill_options", @papermill_options)
144
+ subclass.instance_variable_set("@papermill_associations", @papermill_associations)
145
+ super
146
+ end
147
+ end
148
+
149
+ module InstanceMethods
150
+ attr_writer :timestamp
151
+ def timestamp
152
+ @timestamp ||= "-#{(Time.now.to_f * 1000).to_i.to_s[4..-1]}"
153
+ end
154
+
155
+ def interpolated_path(with = {}, up_to = nil)
156
+ Papermill::papermill_interpolated_path({
157
+ ":assetable_type" => self.class.sti_name.underscore.pluralize,
158
+ ":assetable_id" => self.id
159
+ }.merge(with), up_to)
160
+ end
161
+
162
+ private
163
+
164
+ def rebase_assets
165
+ return true unless timestamp
166
+ PapermillAsset.find(:all, :conditions => {:assetable_id => self.timestamp}).each do |asset|
167
+ if asset.created_at < 2.hours.ago
168
+ asset.destroy
169
+ else
170
+ asset.update_attribute(:assetable_id, self.id)
171
+ end
172
+ end
173
+ system "mv #{interpolated_path({':assetable_id' => timestamp}, ':assetable_id')}/ #{interpolated_path({}, ':assetable_id')}/"
174
+ true
175
+ end
176
+
177
+ def remove_papermill_folder
178
+ system "rm -rf #{interpolated_path({}, ':assetable_id')}/"
179
+ true
180
+ end
181
+ end
182
+ end
data/papermill.gemspec ADDED
@@ -0,0 +1,77 @@
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.1.0"
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-08-30}
13
+ s.description = %q{Paperclip 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
+ "config/locale/papermill.yml",
29
+ "config/routes.rb",
30
+ "generators/papermill/USAGE",
31
+ "generators/papermill/papermill_generator.rb",
32
+ "generators/papermill/templates/migrate/papermill_migration.rb.erb",
33
+ "init.rb",
34
+ "install.rb",
35
+ "lib/core_extensions.rb",
36
+ "lib/papermill.rb",
37
+ "lib/papermill/form_builder.rb",
38
+ "lib/papermill/papermill_asset.rb",
39
+ "lib/papermill/papermill_helper.rb",
40
+ "lib/papermill/papermill_module.rb",
41
+ "papermill.gemspec",
42
+ "public/.DS_Store",
43
+ "public/flashs/swfupload.swf",
44
+ "public/images/.DS_Store",
45
+ "public/images/papermill/.DS_Store",
46
+ "public/images/papermill/background.png",
47
+ "public/images/papermill/container-background.jpg",
48
+ "public/images/papermill/delete.png",
49
+ "public/images/papermill/upload-blank.png",
50
+ "public/images/papermill/upload.png",
51
+ "public/javascripts/papermill.js",
52
+ "public/stylesheets/papermill.css",
53
+ "tasks/papermill_tasks.rake",
54
+ "test/papermill_test.rb",
55
+ "test/test_helper.rb",
56
+ "uninstall.rb"
57
+ ]
58
+ s.homepage = %q{http://github.com/BBenezech/papermill}
59
+ s.rdoc_options = ["--charset=UTF-8"]
60
+ s.require_paths = ["lib"]
61
+ s.rubygems_version = %q{1.3.5}
62
+ s.summary = %q{Paperclip wrapper}
63
+ s.test_files = [
64
+ "test/papermill_test.rb",
65
+ "test/test_helper.rb"
66
+ ]
67
+
68
+ if s.respond_to? :specification_version then
69
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
70
+ s.specification_version = 3
71
+
72
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
73
+ else
74
+ end
75
+ else
76
+ end
77
+ end
Binary file
Binary file
Binary file
@@ -0,0 +1,89 @@
1
+ /*
2
+ Papermill SWFUpload wrapper
3
+ You'll need jQuery or a **very** little bit of rewriting for native/prototype
4
+ */
5
+
6
+ notify = function(message, type) {
7
+ // wrap with your own javascript alert system (here is the thing for jGrowl)
8
+ //if(type == "notice") { jQuery.noticeAdd({ text: message, stayTime: 4000, stay: false, type: type }) }
9
+ //if(type == "warning") { jQuery.noticeAdd({ text: message, stayTime: 9000, stay: false, type: type }) }
10
+ //if(type == "error") { jQuery.noticeAdd({ text: message, stayTime: 20000, stay: false, type: type }) }
11
+
12
+ // or simply
13
+ alert(type + ": " + message)
14
+ }
15
+
16
+
17
+ var Upload = {
18
+ // The total number of files queued with SWFUpload
19
+ files_queued: 0,
20
+
21
+ set_recipient_id: function(dom_id) {
22
+ this.recipient_id = dom_id
23
+ },
24
+ file_dialog_complete: function(num_selected, num_queued)
25
+ {
26
+ // SwfUpload doesn't order uploads by name out of the box...
27
+ this.sorted_queue = [];
28
+ this.index = 0;
29
+ if (num_queued > 0) {
30
+ file_queue = [];
31
+ global_index = 0;
32
+ index = 0;
33
+ do {
34
+ file = this.callFlash("GetFileByIndex", [global_index]);
35
+ if(file != null && file.filestatus == -1) {
36
+ file_queue[index] = file;
37
+ index++;
38
+ }
39
+ global_index++;
40
+ } while (file != null);
41
+ this.sorted_queue = file_queue.sort(function(a,b){
42
+ if(b.name < a.name){return (1)}
43
+ })
44
+ self = this;
45
+ jQuery(this.sorted_queue).each( function(index, file) {
46
+ li = jQuery('<li></li>').attr({ 'id': file.id, 'class': 'swfupload' });
47
+ li.append(jQuery('<span></span>').attr('class', 'name').html(file.name.substring(0, 10) + '...'));
48
+ li.append(jQuery('<span></span>').attr('class', 'status').html(SWFUPLOAD_PENDING));
49
+ li.append(jQuery('<span></span>').attr('class', 'progress').append('<span></span>'));
50
+
51
+ if(self.settings.file_queue_limit == 1) {
52
+ jQuery("#" + self.settings.upload_id).html(li);
53
+ } else {
54
+ jQuery("#" + self.settings.upload_id).append(li);
55
+ }
56
+ })
57
+ this.startUpload(this.sorted_queue[this.index++].id);
58
+ }
59
+ },
60
+
61
+ upload_start: function(file)
62
+ {
63
+ jQuery('#' + file.id + ' .status').html(SWFUPLOAD_LOADING);
64
+ },
65
+ upload_progress: function(file, bytes, total)
66
+ {
67
+ percent = Math.ceil((bytes / total) * 100);
68
+ jQuery('#' + file.id + ' .progress span').width(percent + '%');
69
+ },
70
+ upload_error: function(file, code, message)
71
+ {
72
+ notify(SWFUPLOAD_ERROR + " " + file.name + " (" + message + " [" + code + "])", "error");
73
+ jQuery('#' + file.id).remove();
74
+ },
75
+ upload_success: function(file, data)
76
+ {
77
+ jQuery('#' + file.id).replaceWith(jQuery(data));
78
+ },
79
+ upload_complete: function(file)
80
+ {
81
+ Upload.files_queued -= 1;
82
+ if(this.sorted_queue[this.index]) {
83
+ this.startUpload(this.sorted_queue[this.index++].id)
84
+ }
85
+ },
86
+ file_queue_error: function(file, error_code, message) {
87
+ upload_error(file, error_code, message)
88
+ }
89
+ }
@@ -0,0 +1,33 @@
1
+ .papermill a:hover { background:none; color:inherit; }
2
+ .papermill a img { border:0px; }
3
+ .papermill li:hover { border-color:blue; }
4
+ .papermill li a { display:block; }
5
+ .papermill .progress { display:block; border:1px solid #C2E3EF; text-align:left; height:6px; }
6
+ .papermill .progress span { background:#7BB963; height:6px; width:0; display:block; }
7
+
8
+ .papermill-thumb-container li { border:0px solid transparent; min-height:25px; min-width:25px; }
9
+ .papermill-thumb-container { position:relative; border:5px solid #EEE; padding:4px; overflow-x:hidden; }
10
+ .papermill-thumb-container li { display:block; float:left; position:relative; }
11
+ .papermill-thumb-container .delete { position:absolute; bottom:5px; right:5px; }
12
+ .papermill-thumb-container span { display:block; }
13
+ .papermill-thumb-container .name { font-size:10px; overflow:hidden; font-weight:bold; }
14
+ .papermill-thumb-container .infos { font-size:8px; overflow:hidden; }
15
+ .papermill-thumb-container .status { margin-bottom:10px; }
16
+
17
+ .papermill-asset-container { border:1px solid #EEE; padding:3px; }
18
+ .papermill-asset-container li { display:block; height:22px; }
19
+ .papermill-asset-container .swfupload .name { margin-left:21px; }
20
+ .papermill-asset-container .name { float:left; }
21
+ .papermill-asset-container .status { margin-left:5px; float:left; }
22
+ .papermill-asset-container .progress { float:left; margin-top:6px; margin-left:5px; width:100px; }
23
+ .papermill-asset-container .delete { float:left; margin-top:2px; margin-right:5px; }
24
+
25
+ .papermill-asset-container.papermill-multiple-items { padding-left:10px; border-left:5px solid #EEE; min-height:40px; }
26
+ .papermill-asset-container.papermill-multiple-items li { cursor:row-resize; }
27
+ .papermill-thumb-container.papermill-multiple-items li { cursor:move; }
28
+ .papermill-asset-container.papermill-unique-item { padding-left:5px; min-height:22px; }
29
+
30
+ /* Need some backgrounds?
31
+ .papermill li { background:transparent url(/images/papermill/background.png) repeat top left; }
32
+ .papermill-thumb-container { background:transparent url(/images/papermill/container-background.jpg) repeat top left; }
33
+ */
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class PapermillTest < ActiveSupport::TestCase
4
+ # Replace this with your real tests.
5
+ test "the truth" do
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_support/test_case'
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: BBenezech-papermill
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - "Benoit B\xC3\xA9n\xC3\xA9zech"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-30 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Paperclip wrapper
17
+ email: benoit.benezech@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - .gitignore
26
+ - MIT-LICENSE
27
+ - README.rdoc
28
+ - Rakefile
29
+ - VERSION
30
+ - app/controllers/papermill_controller.rb
31
+ - app/views/papermill/_asset.html.erb
32
+ - app/views/papermill/_raw_asset.html.erb
33
+ - app/views/papermill/_thumbnail_asset.html.erb
34
+ - config/locale/papermill.yml
35
+ - config/routes.rb
36
+ - generators/papermill/USAGE
37
+ - generators/papermill/papermill_generator.rb
38
+ - generators/papermill/templates/migrate/papermill_migration.rb.erb
39
+ - init.rb
40
+ - install.rb
41
+ - lib/core_extensions.rb
42
+ - lib/papermill.rb
43
+ - lib/papermill/form_builder.rb
44
+ - lib/papermill/papermill_asset.rb
45
+ - lib/papermill/papermill_helper.rb
46
+ - lib/papermill/papermill_module.rb
47
+ - papermill.gemspec
48
+ - public/.DS_Store
49
+ - public/flashs/swfupload.swf
50
+ - public/images/.DS_Store
51
+ - public/images/papermill/.DS_Store
52
+ - public/images/papermill/background.png
53
+ - public/images/papermill/container-background.jpg
54
+ - public/images/papermill/delete.png
55
+ - public/images/papermill/upload-blank.png
56
+ - public/images/papermill/upload.png
57
+ - public/javascripts/papermill.js
58
+ - public/stylesheets/papermill.css
59
+ - tasks/papermill_tasks.rake
60
+ - test/papermill_test.rb
61
+ - test/test_helper.rb
62
+ - uninstall.rb
63
+ has_rdoc: false
64
+ homepage: http://github.com/BBenezech/papermill
65
+ licenses:
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --charset=UTF-8
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: "0"
82
+ version:
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.5
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Paperclip wrapper
90
+ test_files:
91
+ - test/papermill_test.rb
92
+ - test/test_helper.rb