Paperclip Ruby Library

repository·master·Indexed 43 days ago

https://github.com/kreeti/kt-paperclip

A Ruby library for handling file attachments in Rails applications. It provides tools for managing models, migrations, and views, supporting various storage adapters like File System, S3, and Fog. Features include image processing via ImageMagick, content type validation, custom processors, and support for styles and thumbnails.

Tokens
10.2K
Snippets
38
Records
48
Agent score
55%

What's inside Paperclip

  1. Create custom attachment processors

    master

    You can extend Paperclip by writing custom processors (e.g., for watermarking or encryption).

    Requirements:

    1. Define the class within the Paperclip module.
    2. Inherit from Paperclip::Processor.
    3. Implement a make method that returns a File.

    Files placed in lib/paperclip or lib/paperclip_processors are automatically loaded. Use the :processors option in has_attached_file to apply them.

    # Example usage of a custom :ocr processor
    has_attached_file :scan, 
                    styles: { text: { quality: :better } },
                    processors: [:ocr]

    Processors are executed in the order defined in the :processors array. Each processor receives the result of the previous one.

    has_attached_file :scan, styles: { text: { quality: :better } },
                             processors: [:ocr]
  2. How IO Adapters work

    master

    Paperclip can accept various input forms like UploadedFile, StringIO, Tempfile, or a URL string.

    Some adapters for non-local sources are not enabled by default for security reasons. To enable them, register them in an initializer (e.g., config/initializers/paperclip.rb):

    • Paperclip::UriAdapter (accepts URI instances)
    • Paperclip::HttpUrlProxyAdapter (accepts http strings)
    • Paperclip::DataUriAdapter (accepts Base64-encoded data: strings)

    Example to enable Data URI support:

    Paperclip::DataUriAdapter.register
  3. Security: Content-Type and Filename Validations

    master

    Starting with version 4.0.0, Paperclip requires that all attachments include either a content type validation, a filename validation, or an explicit instruction that neither is required. This prevents spoofing attacks.

    Example of secure configuration:

    class ActiveRecord::Base
      has_attached_file :avatar
      
      # Option 1: Validate content type
      validates_attachment_content_type :avatar, content_type: /\Aimage/
      
      # Option 2: Validate filename
      validates_attachment_file_name :avatar, matches: [/png\z/, /jpe?g\z/]
      
      # Option 3: Explicitly disable validation
      do_not_validate_attachment_file_type :avatar
    end

    Paperclip also includes a built-in check to prevent content-type spoofing (e.g., an HTML file disguised as a JPEG). This check is limited to the media type (the first part of the MIME type).

    class ActiveRecord::Base
      has_attached_file :avatar
      validates_attachment_content_type :avatar, content_type: /\Aimage/
      validates_attachment_file_name :avatar, matches: [/png\z/, /jpe?g\z/]
      do_not_validate_attachment_file_type :avatar
    end
  4. How Paperclip attributes work

    master

    When you declare has_attached_file :avatar, Paperclip manages four underlying database attributes prefixed with the attachment name:

    • <attachment>_file_name (Required for operation)
    • <attachment>_file_size
    • <attachment>_content_type (Required if using content type validations)
    • <attachment>_updated_at

    By default, only _file_name is required. If you want to validate content types, you must ensure _content_type is present in your schema.

  5. Checking if an attachment exists

    master

    There are two ways to check for file presence, with different performance characteristics:

    1. file? or present?: Checks if the _file_name database column is populated. This is very fast and recommended for loops.
    2. exists?: Checks if the file actually exists on the storage medium. This is slower as it may perform a network request (e.g., to S3).
  6. Use Dynamic Configuration for styles and processors

    master

    You can use lambdas or Procs to define configuration that depends on the specific model instance.

    Dynamic Styles: Define different styles based on an instance attribute (e.g., a user's role):

    class User < ActiveRecord::Base
      has_attached_file :avatar, 
                        styles: lambda { |attachment| 
                          { thumb: (attachment.instance.boss? ? "300x300>" : "100x100>") } 
                        }
    end

    Dynamic Processors: Determine which processors to run based on the instance:

    class User < ActiveRecord::Base
      has_attached_file :avatar, processors: lambda { |instance| instance.processors }
      attr_accessor :processors
    end
    class User < ActiveRecord::Base
      has_attached_file :avatar, styles: lambda { |attachment| { thumb: (attachment.instance.boss? ? "300x300>" : "100x100>") } }
    end
  7. Install kt-paperclip via Gemfile

    master

    To use Paperclip in your application, include the gem in your Gemfile. You can specify a version or use the master branch from the repository.

    # Install a specific version
    gem "kt-paperclip", "~> 8.0"
    
    # Or install from the master branch
    gem "kt-paperclip", git: "git://github.com/kreeti/kt-paperclip.git"
    gem "kt-paperclip", "~> 8.0"
  8. Quick Start: Controller and View implementation

    master

    Controller

    Ensure you permit the attachment parameter in your strong parameters:

    def user_params
      params.require(:user).permit(:avatar)
    end

    Views (Standard Rails)

    Ensure your form uses multipart: true:

    <%= form_for @user, url: users_path, html: { multipart: true } do |form| %>
      <%= form.file_field :avatar %>
      <%= form.submit %>
    <% end %>

    Views (Simple Form)

    <%= simple_form_for @user, url: users_path do |form| %>
      <%= form.input :avatar, as: :file %>
      <%= form.submit %>
    <% end %>

    Displaying Images

    Use the url helper with style names:

    <%= image_tag @user.avatar.url %>
    <%= image_tag @user.avatar.url(:medium) %>
    <%= image_tag @user.avatar.url(:thumb) %>
  9. Configure Paperclip for Parallel Testing

    master

    When running tests in parallel, multiple processes might attempt to write to the same default path, causing collisions. To fix this, include the test environment number in the storage path.

    if ENV['PARALLEL_TEST_GROUPS']
      Paperclip::Attachment.default_options[:path] = ":rails_root/public/system/:rails_env/#{ENV['TEST_ENV_NUMBER'].to_i}/:class/:attachment/:id_partition/:filename"
    else
      Paperclip::Attachment.default_options[:path] = ":rails_root/public/system/:rails_env/:class/:attachment/:id_partition/:filename"
    end
  10. Quick Start: Create Migrations for attachments

    master

    To add attachment support to a table, use the add_attachment migration helper.

    Using add_attachment for existing tables:

    class AddAvatarColumnsToUsers < ActiveRecord::Migration
      def up
        add_attachment :users, :avatar
      end
    
      def down
        remove_attachment :users, :avatar
      end
    end

    Using attachment for new tables:

    class CreateUsersWithAttachments < ActiveRecord::Migration
      def change
        create_table :users do |t|
          t.attachment :avatar
        end
      end
    end

    You can also use the Rails generator: rails generate paperclip user avatar.

  11. Configure validation error placement

    master

    By default, Paperclip copies validation errors from the attachment attribute to the base model. To avoid duplicate errors, use the add_validation_errors_to option.

    Options:

    • :both (Default): Errors appear on both the attribute and the base model.
    • :attribute: Errors appear only on the attribute.
    • :base: Errors appear only on the base model.

    Global configuration: Paperclip.options[:add_validation_errors_to] = :attribute

    Per-validation configuration:

    validates_attachment :document, content_type: { content_type: "application/pdf" }, add_validation_errors_to: :attribute
  12. How Paperclip attachments work

    master

    Paperclip provides a way to manage file attachments within ActiveRecord models without requiring a separate model for attachment metadata. Instead, it adds columns directly to your existing table.

    It uses ImageMagick for graphical transformations (thumbnails/styles) and stores these intermediate files in Tempfiles until the record is saved to the permanent storage backend (like :filesystem, :s3, or :fog).