No commit activity in last 3 years
No release in over 3 years
Paperclip Swfupload UploadHelper wrapper


 Project Readme

Papermill ¶ ↑

  • 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.

Install the gem¶ ↑

sudo gem install papermill

Try the demo¶ ↑

rails -m papermill-example

Out-of-the-box compatibility with : ¶ ↑

  • 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

Navigator minimal requirements: ¶ ↑

  • IE6+

  • Flash 9+

  • Javascript ON

Check your audience.

Server requirements:¶ ↑

  • Rails Installation¶ ↑

    Once gem is installed¶ ↑

    Generate the migration

    ./script/generate papermill_table PapermillMigration

    Edit it and migrate

    rake db: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

    In environment.rb¶ ↑

    ... do |config|
      config.gem papermill

    In your layout¶ ↑

    Quick version¶ ↑

    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 %>
    <% end %>

    Before </body>

    <script src="" type="text/javascript"></script>
    <script src="" 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 %>
    <% end %>

    Security¶ ↑

    URL-hacking¶ ↑

    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 })

    Usage¶ ↑

    Assetable is the class that has_many papermill_assets (i.e. the class with the papermill declaration)

    Assetable 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 :

    class Article
      papermill :default
      papermill :images
      papermill :pdf_version
      papermill :cover_image
      papermill :illustrations

    Form helpers¶ ↑

    Example form:

    form_for @assetable do 
      # 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 feature
      f.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 uploading
      f.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

    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"

    Asset editing ¶ ↑

    • 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.

    Thumbnails¶ ↑

    On-the-fly request time processing:¶ ↑

    PapermillAsset#url(papermill string (see 1.))  # path and url behave the same way
    PapermillAsset#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)

    Render time processing:¶ ↑

    PapermillAsset#url!(papermill string (see 1.))  # path! and url! behave the same way
    PapermillAsset#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.

    1. Papermill String¶ ↑

    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


    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")

    2. Papermill Alias¶ ↑

    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]



    # 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)

    3. Papermill Hash¶ ↑

    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)


    image_tag @article.covers.first.url(
      :geometry => "100x100",
      :watermark => "/images/rails.png",
      :copyright => "papermill",
      :name => "thumbnail_watermarked_and_copyrighted"

    Resource access¶ ↑

    Papermill generates an #<association_key> association

    @entry.diaporamas.each do |image| ..
    # etc.

    Using PapermillAsset¶ ↑

    @asset = @entry.mug_shots.first
    image_tag @asset.url              # original
    image_tag @asset.url("100x>")     # assuming asset is an image
    image_tag @asset.url(:big)        # assuming you have a :big alias
    # etc.

    Translations:¶ ↑

    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