Asset management made easy, 10 minutes integration.
All-you-can-eat glue around Polymorphic Paperclip table, SWFUpload & JQuery.
Associate any image or list of images with any model and any key.
sudogeminstallpapermill
rails -m http://github.com/bbenezech/papermill/raw/master/demo.txt papermill-example
Formtastic # use :as => :[image|asset](s)_upload
JGrowl # for notifications (included)
FaceBox # for popups (included)
Stringex # (or any String#to_url) for asset filename/url generation
IE6+
Flash 9+
Javascript ON
Check your audience.
Rails 2.3.[4~>8]
Paperclip 2.3.1.1 (loaded with gem dependency)
Front web server serving static assets if present, and forwarding demand to rails if not. Any classic installation will do that by default.
NOT compatible with Heroku/S3
Generate the migration
./script/generate papermill_table PapermillMigration
Edit it and migrate
rakedb:migrate
Copy static assets to your public directory
./script/generate papermill_assets
Create the option file config/initializers/papermill.rb
./script/generate papermill_initializer
Go have a look at config/initializers/papermill.rb
... Rails::Initializer.run do |config| ... config.gem papermill end
Inside <head></head>
<%= papermill_stylesheet_tag %>
Before </body> (best practice for javascript loading)
<%= papermill_javascript_tag :with_jquery => "no_conflict" %>
You don’t need :with_jquery if load it by yourself. Pass “no_conflict” if you use the default Prototype library, or some other ‘$’ library (mootools..)
In a real-world production application, you could use something like this, and adapt it to your own needs
Inside <head></head>
<% unless @content_for_papermill_inline_js.blank? %>
<%= javascript_include_tag "/facebox/facebox.js", "/jgrowl/jquery.jgrowl_minimized.js", "/papermill/jquery.Jcrop.min.js", "/swfupload/swfupload.js", "/papermill/papermill.js", :cache => "papermill" %>
<script type="text/javascript">
jQuery(document).ready(function() {
<%= yield :content_for_papermill_inline_js %>
}
</script>
<% end %>Before </body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js" type="text/javascript"></script>
<% unless @content_for_papermill_inline_js.blank? %>
<%= stylesheet_link_tag("/facebox/facebox.css", "/jgrowl/jquery.jgrowl.css", "/Jcrop/jquery.Jcrop.css", "/papermill/papermill.css", :cache => "papermill") %>
<style type="text/css">
<%= yield :papermill_inline_css %>
</style>
<% end %>Maybe you don’t want users to use your application as a thumbnailing farm for their own uploaded images, or you have protected members areas and you don’t want users to ‘browse’ others members file.
Brute solution: pass :use_url_key to true in the options (config/initializers/papermill.rb). A crypted hash unique to your application and to each asset and to the requested style will be added to the URL. No more happy-guessing of anything. Do that first before going live, or you’ll have to migrate all assets…
pass :alias_only to true. This will disable the possibility to generate thumbnails with a papermill string in the url, but won’t do anything for the member area thing. Plus you will have to use aliases only, form helpers included (pass :thumbnail => { :style => :some_alias })
Assetable is the class that has_many papermill_assets (i.e. the class with the papermill declaration)
You can have one :default association (his settings will be used for unfound associations) and as many other associations as you want in your model. You can define a papermill relationship dynamically: just do smtg like Assetable.papermill(:dynamic_key, {}) when you need to. Perfect for CMS where associations are created by users. Then you’ll be able to use assetable.dynamic_key to retrieve the associated assets. If you don’t send the {}, default options from default association will be used, which may or may not be what you want.
Actually, the form helper leverages this when you use a :key that doesn’t exist: it will create a new Papermill relationship whith :key as the name and options from the :default declaration if any found on the model.
If you don’t need dynamic keys, just declare your associations in the model, like this :
classArticlepapermill:defaultpapermill:imagespapermill:pdf_versionpapermill:cover_imagepapermill:illustrationsend
Example form:
form_for@assetabledo# I need a simple asset upload field :f.asset_upload:pdf_version# Now I need to be able to upload as many documents as I need, and sort them at will# no document should be bigger than 1MB (respect the quoting!)# and I don't want the mass_edit featuref.assets_upload:documentation, :swfupload=> { :file_size_limit=>"'1 MB'" }, :mass_edit=>false# I need to display *one* cover *image*, format will be 200x200# targetted_size will give the uploader hints when cropping the image after upload : desired display size and wanted aspect-ratio.# Better than cropping automatically in the center if the character's head is in the upper-left corner..# :thumbnail => { :width & :height } set the dimensions of the preview thumbnail# And finally, I need a 200x200# crop for preview, not the default 200x200> that would be generated by default ("#{:width}x#{:heigth}>")f.image_upload:cover_image, :targetted_size=>"200x200", :thumbnail=> { :width=>200, :height=>200, :style=>"200x200#" } # Now the image gallery, sortable.# I use :gallery => { :lines & :columns } to give the number of lines/columns, # and some CSS will be generated to size the gallery perfectly, # according to the thumb size inside the gallery and their padding/margin/border sizes.# the number of lines will increase if needed when uploadingf.images_upload:illustrations, { :thumbnail=> { :width=>100, :height=>70 }, :gallery=> { :columns=>8, # number of columns:lines=>2, # number of lines:vpadding=>2, # vertical padding around each thumb:hpadding=>2, # horizontal one:vmargin=>3, # vertical margin:hmargin=>1, # horizontal one :border_thickness=>2# border size around each thumb } } end
With Formtastic, pass
:as=> (:image_upload|:images_upload|:asset_upload|:assets_upload)
And add your options as you would with the normal helpers.
With FormTagHelpers, use (image_upload_tag | images_upload_tag | asset_upload_tag | assets_upload_tag) @assetable, :key, options
image_upload_tag@article, :cover_image, :targetted_size=>"200x200"
double-click on any uploaded asset in any form-helper to access & edit his properties
then double-click image to crop it if it’s an image. You’ll then access a Jcrop window. Pass :targetted_size => “widthxheigth” to lock aspect-ratio and default the selection size to widthxheigth.
PapermillAsset#url(papermill string (see 1.)) # path and url behave the same wayPapermillAsset#url(papermill alias (see 2.))
Pros: fast. Nothing done upon page rendering. If asset isn’t found by Apache/NGinx, then request is passed to rails, which will create it, once.
Cons: need to setup an alias in the options if you want to define use a hash instead of a papermill string (for custom watermark)
PapermillAsset#url!(papermill string (see 1.)) # path! and url! behave the same wayPapermillAsset#url!(papermill alias (see 2.))PapermillAsset#url!(papermill hash (see 3.))
Pros: can use a hash directly in the url call.
Cons: needs a thumbnail presence check at each render.
Consist of:
an ImageMagick geometry string (ex: “100x100>”, “original”, “100x#”, etc.)
an optional watermark (-wm) flag # will use option for URI
an optional copyright (©) flag # will use copyright text after the “©” or options
Examples:
image_tag@article.covers.first.url("100x100") image_tag@article.covers.first.url("original©") image_tag@article.covers.first.url("100x100#-wm©") image_tag@article.covers.first.url("100x200#©papermill")
Those are application-wide, set them in the options
Consist of:
:geometry=>"ImageMagick-geometry-string":copyright=>true|"copyright"# If true, the asset copyright field will be used. Edit the asset.:watermark=>true|URI# If true, will use options[:watemark]
Examples:
#config/initilializers/papermill.rb
# snip
:aliases => {
:thumb_copyrighted => {
:geometry => "100x100",
:copyright => "papermill",
},
:thumb_copyrighted_dynamically => {
:geometry => "100x100",
:copyright => true
},
:thumb_watermarked_with_rails => {
:width => "100",
:height => "100",
:watermark => "/images/rails.png"
}
}Then in your views, simply do
image_tag@article.covers.first.url(:thumb_copyrighted)
Same as aliases, but defined directly in #url!() Plus you can add a :name that will be used for style-name (defaults to a md5 of the hash)
Example:
image_tag@article.covers.first.url( :geometry=>"100x100", :watermark=>"/images/rails.png", :copyright=>"papermill", :name=>"thumbnail_watermarked_and_copyrighted" )
Papermill generates an #<association_key> association
@entry.mug_shots.first @entry.diaporamas.each do |image| .. # etc.
@asset = @entry.mug_shots.firstimage_tag@asset.url# originalimage_tag@asset.url("100x>") # assuming asset is an imageimage_tag@asset.url(:big) # assuming you have a :big alias@asset.name@asset.content_type@asset.path@asset.path("100x>") # etc.
Papermill is fully I18n-able. Copy config/locales/papermill.yml to your root config/locale folder to modify any wording in a any locale.
Copyright © 2009 Benoit Bénézech, released under the MIT license
