Giter Club home page Giter Club logo

paperclip's Introduction

Paperclip

Deprecated

Paperclip is deprecated.

For new projects, we recommend Rails' own ActiveStorage.

For existing projects, please consult and contribute to the migration guide, available in English, en español, and as a video recorded at RailsConf 2019. You may also prefer an alternative migration tutorial used by Doorkeeper.

Alternatively, for existing projects, Kreeti is maintaining kt-paperclip, an ongoing fork of Paperclip.

We will leave the Issues open as a discussion forum only. We do not guarantee a response from us in the Issues. All bug reports should go to kt-paperclip.

We are no longer accepting pull requests except pull requests against the migration guide. All other pull requests will be closed without merging.

Existing documentation

Documentation valid for master branch

Please check the documentation for the paperclip version you are using: https://github.com/thoughtbot/paperclip/releases


Build Status Dependency Status Code Climate Inline docs Security

Paperclip is intended as an easy file attachment library for ActiveRecord. The intent behind it was to keep setup as easy as possible and to treat files as much like other attributes as possible. This means they aren't saved to their final locations on disk, nor are they deleted if set to nil, until ActiveRecord::Base#save is called. It manages validations based on size and presence, if required. It can transform its assigned image into thumbnails if needed, and the prerequisites are as simple as installing ImageMagick (which, for most modern Unix-based systems, is as easy as installing the right packages). Attached files are saved to the filesystem and referenced in the browser by an easily understandable specification, which has sensible and useful defaults.

See the documentation for has_attached_file in Paperclip::ClassMethods for more detailed options.

The complete RDoc is online.


Requirements

Ruby and Rails

Paperclip now requires Ruby version >= 2.1 and Rails version >= 4.2 (only if you're going to use Paperclip with Ruby on Rails).

Image Processor

ImageMagick must be installed and Paperclip must have access to it. To ensure that it does, on your command line, run which convert (one of the ImageMagick utilities). This will give you the path where that utility is installed. For example, it might return /usr/local/bin/convert.

Then, in your environment config file, let Paperclip know to look there by adding that directory to its path.

In development mode, you might add this line to config/environments/development.rb):

Paperclip.options[:command_path] = "/usr/local/bin/"

If you're on Mac OS X, you'll want to run the following with Homebrew:

brew install imagemagick

If you are dealing with pdf uploads or running the test suite, you'll also need to install GhostScript. On Mac OS X, you can also install that using Homebrew:

brew install gs

If you are on Ubuntu (or any Debian base Linux distribution), you'll want to run the following with apt-get:

sudo apt-get install imagemagick -y

file

The Unix file command is required for content-type checking. This utility isn't available in Windows, but comes bundled with Ruby Devkit, so Windows users must make sure that the devkit is installed and added to the system PATH.

Manual Installation

If you're using Windows 7+ as a development environment, you may need to install the file.exe application manually. The file spoofing system in Paperclip 4+ relies on this; if you don't have it working, you'll receive Validation failed: Upload file has an extension that does not match its contents. errors.

To manually install, you should perform the following:

Download & install file from this URL

To test, you can use the image below: untitled

Next, you need to integrate with your environment - preferably through the PATH variable, or by changing your config/environments/development.rb file

PATH

1. Click "Start"
2. On "Computer", right-click and select "Properties"
3. In Properties, select "Advanced System Settings"
4. Click the "Environment Variables" button
5. Locate the "PATH" var - at the end, add the path to your newly installed `file.exe` (typically `C:\Program Files (x86)\GnuWin32\bin`)
6. Restart any CMD shells you have open & see if it works

OR

Environment

1. Open `config/environments/development.rb`
2. Add the following line: `Paperclip.options[:command_path] = 'C:\Program Files (x86)\GnuWin32\bin'`
3. Restart your Rails server

Either of these methods will give your Rails setup access to the file.exe functionality, thus providing the ability to check the contents of a file (fixing the spoofing problem)


Installation

Paperclip is distributed as a gem, which is how it should be used in your app.

Include the gem in your Gemfile:

gem "paperclip", "~> 6.0.0"

Or, if you want to get the latest, you can get master from the main paperclip repository:

gem "paperclip", git: "git://github.com/thoughtbot/paperclip.git"

If you're trying to use features that don't seem to be in the latest released gem, but are mentioned in this README, then you probably need to specify the master branch if you want to use them. This README is probably ahead of the latest released version if you're reading it on GitHub.

For Non-Rails usage:

class ModuleName < ActiveRecord::Base
  include Paperclip::Glue
  ...
end

Quick Start

Models

class User < ActiveRecord::Base
  has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
  validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\z/
end

Migrations

Assuming you have a users table, add an avatar column to the users table:

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

  def down
    remove_attachment :users, :avatar
  end
end

(Or you can use the Rails migration generator: rails generate paperclip user avatar)

Edit and New Views

Make sure you have corresponding methods in your controller:

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

Edit and New Views with Simple Form

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

Controller

def create
  @user = User.create(user_params)
end

private

# Use strong_parameters for attribute whitelisting
# Be sure to update your create() and update() controller methods.

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

View Helpers

Add these to the view where you want your images displayed:

<%= image_tag @user.avatar.url %>
<%= image_tag @user.avatar.url(:medium) %>
<%= image_tag @user.avatar.url(:thumb) %>

Checking a File Exists

There are two methods for checking if a file exists:

  • file? and present? checks if the _file_name field is populated
  • exists? checks if the file exists (will perform a TCP connection if stored in the cloud)

Keep this in mind if you are checking if files are present in a loop. The first version is significantly more performant, but has different semantics.

Deleting an Attachment

Set the attribute to nil and save.

@user.avatar = nil
@user.save

Usage

The basics of Paperclip are quite simple: Declare that your model has an attachment with the has_attached_file method, and give it a name.

Paperclip will wrap up to four attributes (all prefixed with that attachment's name, so you can have multiple attachments per model if you wish) and give them a friendly front end. These attributes are:

  • <attachment>_file_name
  • <attachment>_file_size
  • <attachment>_content_type
  • <attachment>_updated_at

By default, only <attachment>_file_name is required for Paperclip to operate. You'll need to add <attachment>_content_type in case you want to use content type validation.

More information about the options passed to has_attached_file is available in the documentation of Paperclip::ClassMethods.

Validations

For validations, Paperclip introduces several validators to validate your attachment:

  • AttachmentContentTypeValidator
  • AttachmentPresenceValidator
  • AttachmentSizeValidator

Example Usage:

validates :avatar, attachment_presence: true
validates_with AttachmentPresenceValidator, attributes: :avatar
validates_with AttachmentSizeValidator, attributes: :avatar, less_than: 1.megabytes

Validators can also be defined using the old helper style:

  • validates_attachment_presence
  • validates_attachment_content_type
  • validates_attachment_size

Example Usage:

validates_attachment_presence :avatar

Lastly, you can also define multiple validations on a single attachment using validates_attachment:

validates_attachment :avatar, presence: true,
  content_type: "image/jpeg",
  size: { in: 0..10.kilobytes }

NOTE: Post-processing will not even start if the attachment is not valid according to the validations. Your callbacks and processors will only be called with valid attachments.

class Message < ActiveRecord::Base
  has_attached_file :asset, styles: { thumb: "100x100#" }

  before_post_process :skip_for_audio

  def skip_for_audio
    ! %w(audio/ogg application/ogg).include?(asset_content_type)
  end
end

If you have other validations that depend on assignment order, the recommended course of action is to prevent the assignment of the attachment until afterwards, then assign manually:

class Book < ActiveRecord::Base
  has_attached_file :document, styles: { thumbnail: "60x60#" }
  validates_attachment :document, content_type: "application/pdf"
  validates_something_else # Other validations that conflict with Paperclip's
end

class BooksController < ApplicationController
  def create
    @book = Book.new(book_params)
    @book.document = params[:book][:document]
    @book.save
    respond_with @book
  end

  private

  def book_params
    params.require(:book).permit(:title, :author)
  end
end

A note on content_type validations and security

You should ensure that you validate files to be only those MIME types you explicitly want to support. If you don't, you could be open to XSS attacks if a user uploads a file with a malicious HTML payload.

If you're only interested in images, restrict your allowed content_types to image-y ones:

validates_attachment :avatar,
  content_type: ["image/jpeg", "image/gif", "image/png"]

Paperclip::ContentTypeDetector will attempt to match a file's extension to an inferred content_type, regardless of the actual contents of the file.


Internationalization (I18n)

For using or adding locale files in different languages, check the project https://github.com/thoughtbot/paperclip-i18n.

Security Validations

Thanks to a report from Egor Homakov we have taken steps to prevent people from spoofing Content-Types and getting data you weren't expecting onto your server.

NOTE: Starting at version 4.0.0, all attachments are required to include a content_type validation, a file_name validation, or to explicitly state that they're not going to have either. Paperclip will raise an error if you do not do this.

class ActiveRecord::Base
  has_attached_file :avatar
  # Validate content type
  validates_attachment_content_type :avatar, content_type: /\Aimage/
  # Validate filename
  validates_attachment_file_name :avatar, matches: [/png\z/, /jpe?g\z/]
  # Explicitly do not validate
  do_not_validate_attachment_file_type :avatar
end

This keeps Paperclip secure-by-default, and will prevent people trying to mess with your filesystem.

NOTE: Also starting at version 4.0.0, Paperclip has another validation that cannot be turned off. This validation will prevent content type spoofing. That is, uploading a PHP document (for example) as part of the EXIF tags of a well-formed JPEG. This check is limited to the media type (the first part of the MIME type, so, 'text' in text/plain). This will prevent HTML documents from being uploaded as JPEGs, but will not prevent GIFs from being uploaded with a .jpg extension. This validation will only add validation errors to the form. It will not cause errors to be raised.

This can sometimes cause false validation errors in applications that use custom file extensions. In these cases you may wish to add your custom extension to the list of content type mappings by creating config/initializers/paperclip.rb:

# Allow ".foo" as an extension for files with the MIME type "text/plain".
Paperclip.options[:content_type_mappings] = {
  foo: %w(text/plain)
}

Defaults

Global defaults for all your Paperclip attachments can be defined by changing the Paperclip::Attachment.default_options Hash. This can be useful for setting your default storage settings per example so you won't have to define them in every has_attached_file definition.

If you're using Rails, you can define a Hash with default options in config/application.rb or in any of the config/environments/*.rb files on config.paperclip_defaults. These will get merged into Paperclip::Attachment.default_options as your Rails app boots. An example:

module YourApp
  class Application < Rails::Application
    # Other code...

    config.paperclip_defaults = { storage: :fog, fog_credentials: { provider: "Local", local_root: "#{Rails.root}/public"}, fog_directory: "", fog_host: "localhost"}
  end
end

Another option is to directly modify the Paperclip::Attachment.default_options Hash - this method works for non-Rails applications or is an option if you prefer to place the Paperclip default settings in an initializer.

An example Rails initializer would look something like this:

Paperclip::Attachment.default_options[:storage] = :fog
Paperclip::Attachment.default_options[:fog_credentials] = { provider: "Local", local_root: "#{Rails.root}/public"}
Paperclip::Attachment.default_options[:fog_directory] = ""
Paperclip::Attachment.default_options[:fog_host] = "http://localhost:3000"

Migrations

Paperclip defines several migration methods which can be used to create the necessary columns in your model. There are two types of helper methods to aid in this, as follows:

Add Attachment Column To A Table

The attachment helper can be used when creating a table:

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

  # This is assuming you are only using the users table for Paperclip attachment. Drop with care!
  def down
    drop_table :users
  end
end

You can also use the change method, instead of the up/down combination above, as shown below:

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

Schema Definition

Alternatively, the add_attachment and remove_attachment methods can be used to add new Paperclip columns to an existing table:

class AddAttachmentColumnsToUsers < ActiveRecord::Migration
  def up
    add_attachment :users, :avatar
  end

  def down
    remove_attachment :users, :avatar
  end
end

Or you can do this with the change method:

class AddAttachmentColumnsToUsers < ActiveRecord::Migration
  def change
    add_attachment :users, :avatar
  end
end

Vintage Syntax

Vintage syntax (such as t.has_attached_file and drop_attached_file) is still supported in Paperclip 3.x, but you're advised to update those migration files to use this new syntax.


Storage

Paperclip ships with 3 storage adapters:

  • File Storage
  • S3 Storage (via aws-sdk-s3)
  • Fog Storage

If you would like to use Paperclip with another storage, you can install these gems along side with Paperclip:

Understanding Storage

The files that are assigned as attachments are, by default, placed in the directory specified by the :path option to has_attached_file. By default, this location is :rails_root/public/system/:class/:attachment/:id_partition/:style/:filename. This location was chosen because, on standard Capistrano deployments, the public/system directory can be symlinked to the app's shared directory, meaning it survives between deployments. For example, using that :path, you may have a file at

/data/myapp/releases/20081229172410/public/system/users/avatar/000/000/013/small/my_pic.png

NOTE: This is a change from previous versions of Paperclip, but is overall a safer choice for the default file store.

You may also choose to store your files using Amazon's S3 service. To do so, include the aws-sdk-s3 gem in your Gemfile:

gem 'aws-sdk-s3'

And then you can specify using S3 from has_attached_file. You can find more information about configuring and using S3 storage in the Paperclip::Storage::S3 documentation.

Files on the local filesystem (and in the Rails app's public directory) will be available to the internet at large. If you require access control, it's possible to place your files in a different location. You will need to change both the :path and :url options in order to make sure the files are unavailable to the public. Both :path and :url allow the same set of interpolated variables.


IO Adapters

When a file is uploaded or attached, it can be in one of a few different input forms, from Rails' UploadedFile object to a StringIO to a Tempfile or even a simple String that is a URL that points to an image.

Paperclip will accept, by default, many of these sources. It also is capable of handling even more with a little configuration. The IO Adapters that handle images from non-local sources are not enabled by default. They can be enabled by adding a line similar to the following into config/initializers/paperclip.rb:

Paperclip::DataUriAdapter.register

It's best to only enable a remote-loading adapter if you need it. Otherwise there's a chance that someone can gain insight into your internal network structure using it as a vector.

The following adapters are not loaded by default:

  • Paperclip::UriAdapter - which accepts a URI instance.
  • Paperclip::HttpUrlProxyAdapter - which accepts a http string.
  • Paperclip::DataUriAdapter - which accepts a Base64-encoded data: string.

Post Processing

Paperclip supports an extensible selection of post-processors. When you define a set of styles for an attachment, by default it is expected that those "styles" are actually "thumbnails." These are processed by Paperclip::Thumbnail. For backward compatibility reasons you can pass either a single geometry string, or an array containing a geometry and a format that the file will be converted to, like so:

has_attached_file :avatar, styles: { thumb: ["32x32#", :png] }

This will convert the "thumb" style to a 32x32 square in PNG format, regardless of what was uploaded. If the format is not specified, it is kept the same (e.g. JPGs will remain JPGs). Paperclip::Thumbnail uses ImageMagick to process images; ImageMagick's geometry documentation has more information on the accepted style formats.

For more fine-grained control of the conversion process, source_file_options and convert_options can be used to pass flags and settings directly to ImageMagick's powerful Convert tool, documented here. For example:

has_attached_file :image, styles: { regular: ['800x800>', :png]}, 
    source_file_options: { regular: "-density 96 -depth 8 -quality 85" },
    convert_options: { regular: "-posterize 3"}

ImageMagick supports a number of environment variables for controlling its resource limits. For example, you can enforce memory or execution time limits by setting the following variables in your application's process environment:

  • MAGICK_MEMORY_LIMIT=128MiB
  • MAGICK_MAP_LIMIT=64MiB
  • MAGICK_TIME_LIMIT=30

For a full list of variables and description, see ImageMagick's resources documentation.


Custom Attachment Processors

You can write your own custom attachment processors to carry out tasks like adding watermarks, compressing images, or encrypting files. Custom processors must be defined within the Paperclip module, inherit from Paperclip::Processor (see lib/paperclip/processor.rb), and implement a make method that returns a File. All files in your Rails app's lib/paperclip and lib/paperclip_processors directories will be automatically loaded by Paperclip. Processors are specified using the :processors option to has_attached_file:

has_attached_file :scan, styles: { text: { quality: :better } },
                         processors: [:ocr]

This would load the hypothetical class Paperclip::Ocr, and pass it the options hash { quality: :better }, along with the uploaded file.

Multiple processors can be specified, and they will be invoked in the order they are defined in the :processors array. Each successive processor is given the result from the previous processor. All processors receive the same parameters, which are defined in the :styles hash. For example, assuming we had this definition:

has_attached_file :scan, styles: { text: { quality: :better } },
                         processors: [:rotator, :ocr]

Both the :rotator processor and the :ocr processor would receive the options { quality: :better }. If a processor receives an option it doesn't recognise, it's expected to ignore it.

NOTE: Because processors operate by turning the original attachment into the styles, no processors will be run if there are no styles defined.

If you're interested in caching your thumbnail's width, height and size in the database, take a look at the paperclip-meta gem.

Also, if you're interested in generating the thumbnail on-the-fly, you might want to look into the attachment_on_the_fly gem.

Paperclip's thumbnail generator (see lib/paperclip/thumbnail.rb) is implemented as a processor, and may be a good reference for writing your own processors.


Events

Before and after the Post Processing step, Paperclip calls back to the model with a few callbacks, allowing the model to change or cancel the processing step. The callbacks are before_post_process and after_post_process (which are called before and after the processing of each attachment), and the attachment-specific before_<attachment>_post_process and after_<attachment>_post_process. The callbacks are intended to be as close to normal ActiveRecord callbacks as possible, so if you return false (specifically - returning nil is not the same) in a before_filter, the post processing step will halt. Returning false in an after_filter will not halt anything, but you can access the model and the attachment if necessary.

NOTE: Post processing will not even start if the attachment is not valid according to the validations. Your callbacks and processors will only be called with valid attachments.

class Message < ActiveRecord::Base
  has_attached_file :asset, styles: { thumb: "100x100#" }

  before_post_process :skip_for_audio

  def skip_for_audio
    ! %w(audio/ogg application/ogg).include?(asset_content_type)
  end
end

URI Obfuscation

Paperclip has an interpolation called :hash for obfuscating filenames of publicly-available files.

Example Usage:

has_attached_file :avatar, {
    url: "/system/:hash.:extension",
    hash_secret: "longSecretString"
}

The :hash interpolation will be replaced with a unique hash made up of whatever is specified in :hash_data. The default value for :hash_data is ":class/:attachment/:id/:style/:updated_at".

:hash_secret is required - an exception will be raised if :hash is used without :hash_secret present.

For more on this feature, read the author's own explanation

Checksum / Fingerprint

A checksum of the original file assigned will be placed in the model if it has an attribute named fingerprint. Following the user model migration example above, the migration would look like the following:

class AddAvatarFingerprintColumnToUser < ActiveRecord::Migration
  def up
    add_column :users, :avatar_fingerprint, :string
  end

  def down
    remove_column :users, :avatar_fingerprint
  end
end

The algorithm can be specified using a configuration option; it defaults to MD5 for backwards compatibility with Paperclip 5 and earlier.

has_attached_file :some_attachment, adapter_options: { hash_digest: Digest::SHA256 }

Run CLASS=User ATTACHMENT=avatar rake paperclip:refresh:fingerprints after changing the digest on existing attachments to update the fingerprints in the database.

File Preservation for Soft-Delete

An option is available to preserve attachments in order to play nicely with soft-deleted models. (acts_as_paranoid, paranoia, etc.)

has_attached_file :some_attachment, {
    preserve_files: true,
}

This will prevent some_attachment from being wiped out when the model gets destroyed, so it will still exist when the object is restored later.


Dynamic Configuration

Callable objects (lambdas, Procs) can be used in a number of places for dynamic configuration throughout Paperclip. This strategy exists in a number of components of the library but is most significant in the possibilities for allowing custom styles and processors to be applied for specific model instances, rather than applying defined styles and processors across all instances.

Dynamic Styles:

Imagine a user model that had different styles based on the role of the user. Perhaps some users are bosses (e.g. a User model instance responds to #boss?) and merit a bigger avatar thumbnail than regular users. The configuration to determine what style parameters are to be used based on the user role might look as follows where a boss will receive a 300x300 thumbnail otherwise a 100x100 thumbnail will be created.

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

Dynamic Processors:

Another contrived example is a user model that is aware of which file processors should be applied to it (beyond the implied thumbnail processor invoked when :styles are defined). Perhaps we have a watermark processor available and it is only used on the avatars of certain models. The configuration for this might be where the instance is queried for which processors should be applied to it. Presumably some users might return [:thumbnail, :watermark] for its processors, where a defined watermark processor is invoked after the thumbnail processor already defined by Paperclip.

class User < ActiveRecord::Base
  has_attached_file :avatar, processors: lambda { |instance| instance.processors }
  attr_accessor :processors
end

Logging

By default, Paperclip outputs logging according to your logger level. If you want to disable logging (e.g. during testing) add this into your environment's configuration:

Your::Application.configure do
...
  Paperclip.options[:log] = false
...
end

More information in the rdocs


Deployment

To make Capistrano symlink the public/system directory so that attachments survive new deployments, set the linked_dirs option in your config/deploy.rb file:

set :linked_dirs, fetch(:linked_dirs, []).push('public/system')

Attachment Styles

Paperclip is aware of new attachment styles you have added in previous deploys. The only thing you should do after each deployment is to call rake paperclip:refresh:missing_styles. It will store current attachment styles in RAILS_ROOT/public/system/paperclip_attachments.yml by default. You can change it by:

Paperclip.registered_attachments_styles_path = '/tmp/config/paperclip_attachments.yml'

Here is an example for Capistrano:

namespace :paperclip do
  desc "build missing paperclip styles"
  task :build_missing_styles do
    on roles(:app) do
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :rake, "paperclip:refresh:missing_styles"
        end
      end
    end
  end
end

after("deploy:compile_assets", "paperclip:build_missing_styles")

Now you don't have to remember to refresh thumbnails in production every time you add a new style. Unfortunately, it does not work with dynamic styles - it just ignores them.

If you already have a working app and don't want rake paperclip:refresh:missing_styles to refresh old pictures, you need to tell Paperclip about existing styles. Simply create a paperclip_attachments.yml file by hand. For example:

class User < ActiveRecord::Base
  has_attached_file :avatar, styles: { thumb: 'x100', croppable: '600x600>', big: '1000x1000>' }
end

class Book < ActiveRecord::Base
  has_attached_file :cover, styles: { small: 'x100', large: '1000x1000>' }
  has_attached_file :sample, styles: { thumb: 'x100' }
end

Then in RAILS_ROOT/public/system/paperclip_attachments.yml:

---
:User:
  :avatar:
  - :thumb
  - :croppable
  - :big
:Book:
  :cover:
  - :small
  - :large
  :sample:
  - :thumb

Testing

Paperclip provides rspec-compatible matchers for testing attachments. See the documentation on Paperclip::Shoulda::Matchers for more information.

Parallel Tests

Because of the default path for Paperclip storage, if you try to run tests in parallel, you may find that files get overwritten because the same path is being calculated for them in each test process. While this fix works for parallel_tests, a similar concept should be used for any other mechanism for running tests concurrently.

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

The important part here being the inclusion of ENV['TEST_ENV_NUMBER'], or a similar mechanism for whichever parallel testing library you use.

Integration Tests

Using integration tests with FactoryBot may save multiple copies of your test files within the app. To avoid this, specify a custom path in the config/environments/test.rb like so:

Paperclip::Attachment.default_options[:path] = "#{Rails.root}/spec/test_files/:class/:id_partition/:style.:extension"

Then, make sure to delete that directory after the test suite runs by adding this to spec_helper.rb.

config.after(:suite) do
  FileUtils.rm_rf(Dir["#{Rails.root}/spec/test_files/"])
end

Example of test configuration with Factory Bot

FactoryBot.define do
  factory :user do
    avatar { File.new("#{Rails.root}/spec/support/fixtures/image.jpg") }
  end
end

Contributing

If you'd like to contribute a feature or bugfix: Thanks! To make sure your fix/feature has a high chance of being included, please read the following guidelines:

  1. Post a pull request.
  2. Make sure there are tests! We will not accept any patch that is not tested. It's a rare time when explicit tests aren't needed. If you have questions about writing tests for paperclip, please open a GitHub issue.

Please see CONTRIBUTING.md for more details on contributing and running test.

Thank you to all the contributors!

License

Paperclip is Copyright © 2008-2017 thoughtbot, inc. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.

About thoughtbot

thoughtbot

Paperclip is maintained and funded by thoughtbot. The names and logos for thoughtbot are trademarks of thoughtbot, inc.

We love open source software! See our other projects or hire us to design, develop, and grow your product.

paperclip's People

Contributors

aboutqx avatar alexgodin avatar betesh avatar bjhess avatar dasch avatar dgynn avatar djcp avatar fxposter avatar georgebrock avatar henrik avatar joshuaclayton avatar maclover7 avatar mike-burns avatar monde avatar morgoth avatar mschulkind avatar murbanski avatar mvanholstyn avatar nickrivadeneira avatar phene avatar princemaple avatar qrush avatar sidraval avatar sikachu avatar soramugi avatar sporky023 avatar tilsammans avatar tute avatar xuanxu avatar zmillman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

paperclip's Issues

Rack::Tempfile with nil filename fails

Reported by Randy Reddig

The HTML 4.01 spec permits multipart form data with an omitted filename.

Rack parses this correctly, and passes a hash describing a file using Rack::Tempfile:

{:type=>"application/octet-stream", 
:head=>"Content-Disposition: form-data; name="profile_image"\r\nContent-Type: application/octet-stream\r\nContent-Transfer-Encoding: binary\r\n", 
:tempfile=>#, 
:name=>"profile_image"}

The original_filename method that Paperclip injects into File returns nil, which fails at attachment.rb:79:

instance_write(:file_name, uploaded_file.original_filename.strip.gsub(/[^\w\d\.\-]+/, '_'))

I suppose a reasonable fix would be to use the tempfile’s filename as a substitute for the missing filename field.

Move temp file instead of copy

Reported by Dmitry Smalko

Is it possible to configure paperclip to make it move files from /tmp to store location instead of copy?

Problem is that large file takes too much time to copy. For example 1.4Gb file needs about 80sec to copy and SWFUpload goes timeout.

[...]

iostream.rb:

def to_tempfile tempfile = Tempfile.new("stream") 
  tempfile.binmode self.stream_to(tempfile) 
end

changes to..

def to_tempfile 
  self.rewind self 
end

On large files it works many times faster

Add Rackspace/Mosso Cloud Files support

Reported by minter

I've added support for Rackspace/Mosso Cloud Files, an S3 competitor, in my github fork (http://github.com/minter/paperclip/tree/master). I've included tests, based off of the existing S3 tests.

The Cloud Files support requires the Cloud Files Ruby gem, currently available at http://www.mosso.com/cloudfiles.jsp but hopefully soon in a more standard location.

I'm hoping this will be a useful addition to Paperclip, giving users another option for hosting their data in a cloud environment.

Paperclip / Right_AWS & Content_Type Issue

Hey there. I'm having a weird issue when trying to rake refresh paperclip after initally setting it up to use s3 storage. The following is the error:

undefined method `content_type' for #
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:57
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:26:in `for_all_attachments'
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:24:in `each'
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:24:in `for_all_attachments'
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:22:in `each'
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:22:

Could anyone lend a hand? I've upgraded Ruby to 1.8.7, Updated all Gems / Plugins, Tried using AWS/S3 gem instead of Right_AWS (doesn't work). I'm attempting to upload images and mp3s. Though the issue occurs even when I turn off the mp3 uploading...

to_file method for s3 Storage

Reported by Giovanni Cangiani

Hi,

the to_file method for s3 Storage does not return a File object but an RightAws::S3::Key instead. This is consistent with the comment in the code (in the format most representative of the current storage), but not with what the reprocess! method in Attachment expects (an object that responds to "read" method).

I am willing to submit a patch for this but there are two ways and I'd like to know which one you prefer.

  1. actually write the s3_bucket.key.data into a Tempfile and return the file
  2. implement read/write methods for RightAws::S3::Key
    What do you think ?

Last question. Is there any foundamental reason for chosing RightAWS instead of the usual AWS::S3 ?

Thanks,

giovanni

Patch to allow per style S3 permissions

Reported by Andrew

I have forked and patched paperclip on github at http://github.com/andrewtimberlake/paperclip/commit/5b2f2e6fb6abf9625cbf50cd59f86267cfc0a83d

This change allows you to set a hash for s3_permissions like
:s3_permissions => {:original => 'private', :thumb => 'public-read'}
This is useful for a situation where a cropped thumbnail needs to be quick to download but the original file needs to be protected (and it's download might be managed through the web app itself instead of directly off S3)
You can also set a :default key in your permissions hash which will apply to all styles except those specifically stated.

The original functionality is unchanged as s3_permissions can still accept a string which will apply to all styles.

Includes tests

JRuby: Permission denied on file move

Reported by Karl-Heinz Köther:

Hi,

I built a small application (one model, paperclip 2.2.5) on Ubuntu HardyHeron (4.08).

class Clip < ActiveRecord::Base
  has_attached_file :photo, :styles => { :small => "300x300>" },
   :url => "/assets/photos/:id/:style/:basename.:extension",
   :path => ":rails_root/public/assets/photos/:id/:style/:basename.:extension"
end

With the standard C-Ruby 1.8.6 and Rails 2.2.2 it works fine.

But the same Code with JRuby I got an error when I want to save a record.

My environment: JDK 1.6.0_11 or 1.6.0_12, JRuby 1.1.6, Rails 2.2.2

From the logs:

Errno::EACCES in ClipsController#create 
Permission denied - Permission denied - /tmp/stream20090216-8069-1r49ujo-0 or /home/[...]/PaperClip_JRuby/public/assets/photos/1/original/rails.png
/opt/JRuby/khk/jruby-1.1.6-22/lib/ruby/1.8/fileutils.rb:505:in `mv'
/opt/JRuby/khk/jruby-1.1.6-22/lib/ruby/1.8/fileutils.rb:1395:in `fu_each_src_dest'
/opt/JRuby/khk/jruby-1.1.6-22/lib/ruby/1.8/fileutils.rb:1411:in `fu_each_src_dest0'
/opt/JRuby/khk/jruby-1.1.6-22/lib/ruby/1.8/fileutils.rb:1393:in `fu_each_src_dest'
/opt/JRuby/khk/jruby-1.1.6-22/lib/ruby/1.8/fileutils.rb:494:in `mv'
vendor/plugins/paperclip/lib/paperclip/storage.rb:44:in `flush_writes'
vendor/plugins/paperclip/lib/paperclip/storage.rb:40:in `each'
vendor/plugins/paperclip/lib/paperclip/storage.rb:40:in `flush_writes'
vendor/plugins/paperclip/lib/paperclip/attachment.rb:152:in `save'
vendor/plugins/paperclip/lib/paperclip.rb:299:in `save_attached_files'
vendor/plugins/paperclip/lib/paperclip.rb:292:in `each_attachment'
vendor/plugins/paperclip/lib/paperclip.rb:291:in `each'
vendor/plugins/paperclip/lib/paperclip.rb:291:in `each_attachment'
vendor/plugins/paperclip/lib/paperclip.rb:298:in `save_attached_files'
[...]

Thanks for help

karl-heinz

Styles with different format are uploaded to S3 with the wrong content-type

If you have styles that convert an image (say from SVG to PNG) and are using S3 for storage, then the wrong content type will be uploaded to S3. The content type from the original will be used to set the content type for all styles.

For details see the previous lighthouse ticket here: https://thoughtbot.lighthouseapp.com/projects/8794/tickets/144-styles-with-different-format-are-uploaded-to-s3-with-the-wrong-content-type#ticket-144-6

The patch is these two commits (courtesy of S. Brent Faulkner):
http://github.com/sbfaulkner/paperclip/commit/50a156f8fe6f8f9d5c8fd51eb47506e43d7bdda4
http://github.com/sbfaulkner/paperclip/commit/dd773d20d3fc555f48440c5aa6130af565df448b

Paperclip fails silently, unable to insert any data into database.

I am writing a web service that will allow users to upload files into the system. I have performed the steps as suggested in the tutorial. However, when I submit the form(new) I don't see anything inserted into the database. The server console doesn't show any error messages either. I also have imagemagick and rmagick gem installed. I am running the latest version of rails on ubuntu jaunty. My code is included below:

Below is the description of my table:

mysql> desc videos;
+------------------+--------------+------+-----+---------+----------------+
| Field            | Type         | Null | Key | Default | Extra          | 
+------------------+--------------+------+-----+---------+----------------+
| id               | int(11)      | NO   | PRI | NULL    | auto_increment | 
| vid_file_name    | varchar(255) | YES  |     | NULL    |                | 
| vid_content_type | varchar(255) | YES  |     | NULL    |                | 
| vid_file_size    | int(11)      | YES  |     | NULL    |                | 
| cameraid         | int(11)      | YES  |     | NULL    |                | 
| video_from       | datetime     | YES  |     | NULL    |                | 
| video_to         | datetime     | YES  |     | NULL    |                | 
| numframes        | int(11)      | YES  |     | NULL    |                | 
| fps              | int(11)      | YES  |     | NULL    |                | 
| hres             | int(11)      | YES  |     | NULL    |                | 
| vres             | int(11)      | YES  |     | NULL    |                | 
| vid_calib_info   | text         | YES  |     | NULL    |                | 
| obj_ids          | text         | YES  |     | NULL    |                | 
| misc             | text         | YES  |     | NULL    |                | 
| notes            | text         | YES  |     | NULL    |                | 
| created_by       | varchar(255) | YES  |     | NULL    |                | 
| location         | varchar(255) | YES  |     | NULL    |                | 
| created_at       | datetime     | YES  |     | NULL    |                | 
| updated_at       | datetime     | YES  |     | NULL    |                | 
+------------------+--------------+------+-----+---------+----------------+

My Model and Controller are as follows:

class Video < ActiveRecord::Base
    #validates_attachment_presence :vid
    has_attached_file :vid, :styles => {:thumb => "100x100#"}
end



# GET /videos/new
# GET /videos/new.xml
def new
    @video = Video.new
    RAILS_DEFAULT_LOGGER.debug "creating new object"

   respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @video }
   end
end

# GET /videos/1/edit
def edit
  @video = Video.find(params[:id])
end

# POST /videos
# POST /videos.xml
def create
  RAILS_DEFAULT_LOGGER "before object"
  @video = Video.new(params[:video])
  RAILS_DEFAULT_LOGGER "created object"

  respond_to do |format|
    if @video.save
      flash[:notice] = 'Video was successfully created.'
      format.html { redirect_to(@video) }
      format.xml  { render :xml => @video, :status => :created, :location => @video }
    else
      format.html {
                    RAILS_DEFAULT_LOGGER "error creating object" + @video.errors
                    render :action => "new"
                }
      format.xml  { render :xml => @video.errors, :status => :unprocessable_entity }
    end
  end
end

The following lines in the form have been changed:
<% form_for :video, :html => {:multipart => true} do |f| %>
<%= f.error_messages %>

 <p>
   <%= f.label :vid_file_name %><br />
   <%= f.file_field :vid %>
 </p>

When I upload a fill the form with a new file, I see the following on the server console:

Processing VideosController#new (for 127.0.0.1 at 2009-06-09 23:32:56) [POST]
   Parameters: {"commit"=>"Create",   "authenticity_token"=>"1183HJ8CLm9WV88iomd42PrwqSYSdzwCWwTN9JU5BNM=", "video"=>{"video_to(2i)"=>"6", "location"=>"", "misc"=>"", "vres"=>"", "video_to(3i)"=>"10", "hres"=>"", "video_to(4i)"=>"03", "cameraid"=>"", "notes"=>"", "numframes"=>"", "video_to(5i)"=>"30", "video_from(1i)"=>"2009", "video_from(2i)"=>"6", "vid_file_size"=>"", "created_by"=>"", "video_from(3i)"=>"10", "vid_content_type"=>"", "video_from(4i)"=>"03", "vid"=>#<File:/tmp/RackMultipart20090609-25055-oists5-0>, "video_from(5i)"=>"30", "obj_ids"=>"", "vid_calib_info"=>"", "fps"=>"", "video_to(1i)"=>"2009"}}
Video Columns (1.5ms)   SHOW FIELDS FROM `videos`

Any pointers as to what I am doing incorrectly?

gs not found during tests on os-x

Reported by Kelly Felkins

My model has this declaration: has_attached_file :entity, :styles => { :small => ["400x400>", :png] }

I have a model spec that creates a model object and saves it. The attachment is a pdf file. This was failing with something like "...6192.0 is not recognized by the 'identify' command". This appears to work fine in development mode.

Apparently imagemagick relies on ghostscript when dealing with pdf files. Paperclip would issue the identify command prefixed with a command_path. Then identify would attempt a gs, but the gs command is not in the path.

My quick fix was to add the command_path to the path before issuing the identify command, like this:

export PATH=/opt/local/bin:$PATH;identify...

$ identify --version Version: ImageMagick 6.4.9-6 2009-03-08 Q16 http://www.imagemagick.org Copyright: Copyright (C) 1999-2009 ImageMagick Studio LLC $ gs --version 8.64

Paperclip uses before_destroy slightly incorrectly

Paperclip should probably use after_destroy to remove authenticated files, since before_destroy hooks have the power to stop the object's destruction. If paperclip's hook runs (removing the files), and then another hook stops the destruction, the object is left with a half-dead attachment. Here is a patch which addresses the issue. Essentially, changing before_destroy to after_destroy, and modifying the Attachment class to not mess with the instance properties if they are frozen (i.e. it's being destroyed).

Allow file_name column to be missing

Reported by James Le Cuirot

I hate it when file plugins force you to have a file_name column when it’s obvious what the filename is going to be – such as when it’s something like :id.csv. This patch allows you to not have the column as long as the :path option doesn’t use :basename or :extension. I’ve added tests but I haven’t tested against S3. This approach is not ideal for S3 anyway because it calls exists? to determine whether a file is attached or not.

http://github.com/chewi/paperclip

Easy Custom Interpolations

Reported by Michael Boutros

Hello! Recently I needed to add some custom interpolations for an attachment, and I thought the current way of having to add one through an initializer was cumbersome and kind of hackish, so I've coded up a much easier method and submitted a pull request at Github. The commit: http://github.com/michaelboutros/paperclip/commit/d693882e587dff2d737527c4298ed802b26a3b50

From the docs I wrote under #has_attachment:

+interpolations+: Takes a hash of {:name => proc|lambda} and adds each pair to the
interpolations array. See Attachment#interpolations for more information on interpolations. For example:

  has_attached_file :avatar, :styles => { :normal => "100x100#" },
                    :default_style => :normal,
                    :url => "/:attachment/:id/:style/:user_info.:extension",
                    :path => ":rails_root/public/:attachment/:id/:style/:user_info.:extension"
                    :interpolations =>
                      { :user_info => proc {|attachment, style| attachment.instance.name + '_' + attachment.instance.id + '_' + style } }

What does everyone think? https://thoughtbot.lighthouseapp.com/attachments/70827/easy_custom_interpolations.diff

rake paperclip:refresh class name error for nested model

Rake task for nested ActiveRecord model eg. Namespace1::ModelName fails.

Error log:
/paperclip/tasks/paperclip_tasks.rake:5:in const_get' /paperclip/tasks/paperclip_tasks.rake:5:inobtain_class'
/paperclip/tasks/paperclip_tasks.rake:19:in `for_all_attachments'
/paperclip/tasks/paperclip_tasks.rake:55

Paperclip::Interpolations redefines class

The Paperclip::Interpolations class redefines the class method it inherits from Object, and give it a different signature.

We're trying to track down a memory leak, and I'm interating through the ObjectSpace with each_object, and trying to count the objects by class. But it blows up with an error:

wrong number of arguments (0 for 2)

Override such fundamental pieces of the ruby standard library such as Object.class just strikes be as a very bad idea.

use to_param instead of id for interpolations

Reported by Jessy

I don't know if I am missing something, but it looks like I can't use anything else than the object id to name the attachment.

I think it would be prettier if the :id key that I use to define my attachment url was binded to the to_param method of my object first so that i can override it easily.

in /paperclip/attachment.rb

def self.interpolations
 ...
 :id           => lambda{|attachment,style| attachment.instance.to_param || attachment.instance.id }
 end

Phusion Passenger (mod_rails) Environment Issues on OSX

Reported by mat:

We used paperclip in our project. In production it worked great (Debian box). On our OSX boxes in development it worked great until we switched to Phusion (aka mod_rails). When running under Phusion we'd get this error:

ActionView::TemplateError (can't convert Array into String) on line #4 of vendor/plugins/active_scaffold/frontends/default/views/_form_messages.rhtml:
1: <%= render :partial => 'messages' %>
2: 
3: <% unless @record.nil? %>
4:     <%= error_messages_for 'record' %>
5: <% end %>

    vendor/plugins/active_scaffold/lib/extensions/error_messages.rb:18:in `+'
    vendor/plugins/active_scaffold/lib/extensions/error_messages.rb:18:in `as_full_messages'

This error is caused by our ActiveScaffold horking on an error thrown by paperclip. Paperclip is failing because ImageMagick is returning nothing - just a blank - because the environment variable $MAGICK_HOME isn't set. You see it's difficult to set the environment variables ImageMagick needs in Phusion (see http://code.google.com/p/phusion-passenger/issues/detail?id=81). There are two solutions:

  1. Install ImageMagick in your /usr/bin folder using Ports
  2. Hack apache to run a special Ruby with environment variables defined (see http://code.google.com/p/phusion-passenger/issues/detail?id=81)

Neither one of these work for us. Ports is problematic (long story) and the apache hack means we would have to run a different config for development and production.

Instead we developed a very small patch to paperclip that introduces a new parameter MAGICK_HOME alongside COMMAND_PATH. With this patch, on any Phusion box you can avoid installing ImageMagick into the /usr/bin folder and instead do this:

  • Apply the patch included in this ticket
  • Download and uncompress Image Magick into somewhere convenient. We put it in /usr/local/imagemagick
  • Add this as an initializer in $PROJECT/config/initializers/paperclip.rb:
# config/initializers/paperclip.rb
if RAILS_ENV == "development"
 Paperclip.options[:command_path] = '/usr/local/imagemagick/bin'
 Paperclip.options[:magick_home] = '/usr/local/imagemagick'
end

Don't forget to restart your project after you do the above.

Our patch may be lacking in some way, it seems to work for us so far.

EDIT: Here's the correct patch for this:

Index: paperclip.rb
===================================================================
--- paperclip.rb    (revision 236)
+++ paperclip.rb    (working copy)
@@ -57,7 +57,8 @@
       @options ||= {
         :whiny_thumbnails  => true,
         :image_magick_path => nil,
-        :command_path      => nil
+        :command_path      => nil,
+        :magick_home       => nil
       }
     end
 
@@ -70,6 +71,9 @@
     end
 
     def run cmd, params = "", expected_outcodes = 0
+      if options[:magick_home]
+        ENV['MAGICK_HOME'] = options[:magick_home]
+      end
       output = `#{%Q[#{path_for_command(cmd)} #{params} 2>#{bit_bucket}].gsub(/\s+/, " ")}`
       unless [expected_outcodes].flatten.include?($?.exitstatus)
         raise PaperclipCommandLineError, "Error while running #{cmd}"

rake paperclip:refresh class name error for nested model

Rake task for nested ActiveRecord model eg. Namespace1::ModelName fails.

Error log:
/paperclip/tasks/paperclip_tasks.rake:5:in const_get' /paperclip/tasks/paperclip_tasks.rake:5:inobtain_class'
/paperclip/tasks/paperclip_tasks.rake:19:in `for_all_attachments'
/paperclip/tasks/paperclip_tasks.rake:55

Warn the user when no styles are defined, but a processor is.

If no styles are defined, no processing is run as paperclip does not process the original file by default. If there is a processor specified but no styles, the user should be warned so there is some indication of why they are not seeing their processor working.

Missing uploaded files, maybe because of too many files open

Hi guys, I'm running on Dev ENV, paperclip version 2.2.8, rails 2.1.2.
Here is the problem. Sometimes i get that error that says "Too many open files" and the server crashes, i have to start again the mongrel daemon. sometimes i think its probably when i upload many files off course. I don't think is because of reading the files, but i'm not sure. Thats one problem, and i think that probably is because of that, that i am missing files, i don't know exactly when just, one day to another, the files are gone.
Step 1, upload a photo
Step 2, Check that photo is uploaded
Note: in this step sometimes the image is not saved in all the sizes i declared on the model.
Step 3, Check the thumb in the list view.
Everything seems to be fine.

Days after the images are gone... Please tell me what else do you need to track the bug, maybe the mongrel log, or the development log or something. Just tell me and i'll post it

Proc argument given to :processors only called once

I have some extra attributes on my model that has_attached_file (ProductImage), implemented using attr_accessor. I have form fields that allow the selection of these options. I want the selection of an option on the upload form to drive which processors are run on the uploaded file. e.g., checkbox for 'drop_shadow' would call the drop_shadow processor, then thumbnail.

I've implemented this as follows: http://gist.github.com/128168

This all seems to work great the first time a file is uploaded, after that it doesn't appear as though the proc is being called. I've verified this by adding a Rails logger call to Time.now.to_f

My guess is that some type of memorization is happening or something, but am not familar enough with Paperclip to verify this.

I'm using Ruby Enterprise Edition 20090520, Passenger 2.2.2 on Apache 2.2.8 on Ubuntu 8.04.2.

Support additional mime types

Reported by thibaut Assus

In file lib/paperclip/upfile.rb Module Upfile method content_type I was wondering if it was possible to add our proper mime types (as mp3) It would be wonderful !

must provide both :url and :path options to has_attached_file

Reported by David Lowenfels

has_attached_file :image, :styles => { :original => "300x>" },
                            :url => "/attachments/:class/:id/:style_:basename.:extension",
                            :path => ":rails_root/public/attachments/:class/:id/:style_:basename.:extension"

:path is not mentioned in the docs for has_attached_file, only in attachment.rb
I was surprised that I had to explicitly set :path (upload path) in order to get this to work properly. The POLS thing to do would be to set :path => ":rails_root/public#{:url}" if path is not explicitly supplied.

Using Rails' Built-in Asset Hosts for S3-stored Attachments

Reported by Marshall Sontag

The Problem:

I recently decided to move all of my assets, including paperclip attachments, to S3/Cloudfront. To take advantage of Rails' built-in support for multiple asset hosts, I created 4 CNAME subdomains (assets0.domain.com, assets1.domain.com, etc) that all forwarded to Cloudfront. However, because Paperclip was set to s3 storage, it would only return an S3-based URL, or it would allow me to specify only a single CNAME host. I could not use Rails' built-in asset_host settings to serve my assets.

The Solution:

Rails' built-in image_tag helper (more specifically, the image_path helper) will use the asset_host setting in your environment (if set) to calculate what the URL should be. In order to do this, it needs to be handed a relative URL (i.e. "photos/1/image.jpg"). Paperclip is not currently equipped to return a relative URL when using S3 Storage, so it needs this ability. Toward this end, I created a 4th option for the S3 :url setting (which I have called :asset_host) that returns a relative path so that Rails can do the proper URL calculation.

The Patch:

Fresh commit, complete with leading slash and 2 different asset host settings. One with bucket for S3, one without bucket for Cloudfront:

http://github.com/marshmallowcreme/paperclip/tree/master

image validation

Reported by Josh Pencheon

I think it would be really helpful to be able to validate an attachment as an image. At the moment, I'm doing this like this:

 ALLOWED_CONTENT_TYPES = {
    'MS Word'       => 'doc',
    'MS Excel'      => 'xls',
    'MS Powerpoint' => 'ppt',
    'Adobe PDF'     => 'pdf',
    'ZIP'           => 'zip',
    'JPEG'          => 'jpeg',
    'GIF'           => 'gif',
    'PNG'           => 'png',
    'text'          => 'txt'
  }

APPLICATION_REGEXP = %r{^(x-)?application/#{ALLOWED_CONTENT_TYPES.values.join('|')}$}
IMAGE_REGEXP = %r{^(image|(x-)?application)/(x-png|pjpeg|jpeg|jpg|png|gif)$}  
  
validates_attachment_presence :document
validates_attachment_content_type :document, 
    :content_type => [ APPLICATION_REGEXP, IMAGE_REGEXP, 'text/plain' ],
    :message => "must be: #{ALLOWED_CONTENT_TYPES.values.map{|k| '.' + k }.join(' ')}"

Which is ugly, but I'm not sure what to do. However, now I need this functionality in another model, and don't want to duplicate it.

In attachment_fu, I think you can do something like this:

validates_content_type_of_attachment :image

Thanks, Josh

I've had a go at making a patch (it's tested): https://thoughtbot.lighthouseapp.com/attachments/70915/image_validation_additions.diff

Hope it might be helpful!

SystemStackError with S3

Reported by sam:

Hi,

The latest version of of paperclip (as of 2009-05-21) has a major issue with S3 storage. Attempts to do anything related to paths or URLs (so basically everything) result in a SystemStackError: stack level too deep.

Here's a sample of output:

SystemStackError: stack level too deep
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/storage.rb:149:in `s3_path_url'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:31:in `send'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:31:in `interpolate'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:30:in `gsub'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:30:in `interpolate'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/attribute_methods.rb:211:in `inject'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:29:in `each'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:29:in `inject'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:29:in `interpolate'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/attachment.rb:391:in `interpolate'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/attachment.rb:103:in `url'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:46:in `url'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:31:in `send'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:31:in `interpolate'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:30:in `gsub'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:30:in `interpolate'
... 6074 levels...
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:29:in `inject'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:29:in `interpolate'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/attachment.rb:391:in `interpolate'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/attachment.rb:112:in `path'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/storage.rb:149:in `s3_path_url'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:31:in `send'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:31:in `interpolate'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:30:in `gsub'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:30:in `interpolate'
    from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/attribute_methods.rb:211:in `inject'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:29:in `each'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:29:in `inject'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/interpolations.rb:29:in `interpolate'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/attachment.rb:391:in `interpolate'
    from /Users/sam/workspace/FloresFrescas.com/vendor/plugins/paperclip/lib/paperclip/attachment.rb:103:in `url'

I'm guessing this has something to do with the new default style code. When I reverted to a version of the plugin from March (commit a1b39cc) I had no problems. I've not tried any other revisions.

Cheers,
sam

Okay, I managed to stumble upon a fix. Simply by adding the :path to the has_attached_file it operates as it should do. I didn't realise this was a requirement, but after testing older versions and getting problems with saving to S3 I found adding :path was the only way to get anything to work.

Cheers, sam

If imagemagick doesn't have PNG support, paperclip fails silently

Reported by Philip Hallstrom

One of my hosts has imagemagick without PNG support (argh!). When uploading PNG's none of the thumbnails would be generated.

While debugging I find that the first thing paperclip does is run this:

identify -format "%wx%h" "/tmp/stream20081113-4432-msgp7k-0" 2>/dev/null

When I run that manually I get this:

$ identify -format "%wx%h" "/tmp/stream20081113-4432-msgp7k-0"
identify: no decode delegate for this image format `/tmp/stream20081113-4432-msgp7k-0'.
$ echo $?
1

As near I can tell any error status beyond zero should raise an error, but no error is raised and I see nothing in the logs.

Add option to delegate attachment methods to the model

Reported by Andrew Vit

Paperclip often doesn't fit the 1:1 user.avatar and person.portrait paradigm. I'm contributing a small but hopefully useful patch for the following scenario:

class Album < ActiveRecord::Base
  has_many :photos
end

class Photo < ActiveRecord::Base
  has_attached_file :photo
end

To get the url for an album photo, we need to reach into the paperclip attachment attribute of the photo model, which looks messy because the photo model and the attachment should just represent the same thing:

photo = album.photos.first

# Ok, this example is purposefully confusing:
photo.photo.url

# But it doesn't really matter what we call the attachment,
# It's still some potentially confusing method chaining:
photo.attachment.url
photo.image.url
photo.file.url
photo.upload.url

# Much clearer would be just:
photo.url

This simple patch adds the following syntax:

class AlbumPhoto < ActiveRecord::Base
  has_attached_file :photo
  delegate_attachment_methods_for :photo
end

The following methods would be available directly on the model:

photo.url
photo.path
photo.content_type
photo.original_filename
photo.size

Patch: http://gist.github.com/124434

asset urls and relative_url_root

Reported by Anthony Underwood

Most of my applications have roots which are a sub_url of the root url (In passenger I use RailsBaseURI /app_name)

Therefore in my environment.rb file I use the line

config.action_controller.relative_url_root = app_name

paperclip assets do not seem to take consideration of this config.

for example, asset.url generates:

/datas/1/original/Pic.jpg?1226756334

rather than

app_name/datas/1/original/Pic.jpg?1226756334

I have tried with the latest version of paperclip which prepends system before datas but there is no inclusion of the app_name sub_url

this could be fixed by something like :url => "#{ActionController::Base.relative_url_root}/system/:attachment/:id/:style/:basename.:extension"

line 9 of lib/paperclip/attachment.rb

Is this something that could be looked into please?

Thanks Anthony

STI subclasses share validations defined in other subclasses

Reported by Dave Krupinski

When using paperclip in STI models each subclass contains all validations defined in any of the subclasses.

Example:

Asset < ActiveRecord::Base has_attached_file :image has_attached_file :video end

Video < Asset validates_attachment_presence :video end

Image < Asset validates_attachment_presence :image end

Image and Video will incorrectly require the presence of both a video and an image.

Undefined Method `content_type' Error on Refresh

Hey guys is there anyone who can lend a hand? I'm pulling my hair out at this issue.

Everything works fine locally, and RightAws CAN connect to S3, but when switching paperclip to S3 storage, I get the following error on refresh:

undefined method `content_type' for #
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:57
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:26:in `for_all_attachments'
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:24:in `each'
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:24:in `for_all_attachments'
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:22:in `each'
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:22:in `for_all_attachments'
/Users/praveen/Sites/percussionlab/vendor/plugins/paperclip/tasks/paperclip_tasks.rake:54
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:636:in `call'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:636:in `execute'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:631:in `each'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:631:in `execute'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:597:in `invoke_with_call_chain'
/usr/local/lib/ruby/1.8/monitor.rb:242:in `synchronize'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:590:in `invoke_with_call_chain'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:607:in `invoke_prerequisites'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:604:in `each'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:604:in `invoke_prerequisites'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:596:in `invoke_with_call_chain'
/usr/local/lib/ruby/1.8/monitor.rb:242:in `synchronize'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:590:in `invoke_with_call_chain'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:583:in `invoke'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2051:in `invoke_task'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2029:in `top_level'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2029:in `each'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2029:in `top_level'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2068:in `standard_exception_handling'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2023:in `top_level'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2001:in `run'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:2068:in `standard_exception_handling'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake.rb:1998:in `run'
/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/bin/rake:31
/usr/local/bin/rake:19:in `load'
/usr/local/bin/rake:19

Is there at least any way to switch paperclip to use the AWS::S3 gem instead? I could at least try that? Anyone have any ideas?

Support for I18n

Reported by Peter Suschlik

I've added I18n support for error messages:
http://github.com/splattael/paperclip/tree/translate_error_message

Now you can define translations for the errors messages in e.g. your YAML locale file:

en:
  paperclip:
    errors:
      attachment:
        size: "Invalid file size"
        content_type: "Unsupported content type"
        presence: "Cant' be blank"

I fear my tests are a bit messy... I'm new to shoulda :/

Nevertheless, I hope you like the patch :)

Copying s3-based attachments

Reported by Dylan Markow

Using S3, it doesn't seem that copying attachments from one record to another works. The comments in attachment.rb state that "In addition to form uploads, you can also assign another Paperclip attachment: new_user.avatar = old_user.avatar", but when I try this, the second record's attachment remains empty and nothing gets uploaded to amazon's servers.

a = Post.find(1)
b = Post.find(2)
a.attachment_file_name
# => "Attachment.pdf"
b.attachment_file_name
# => nil
b.attachment = a.attachment
b.save
b.attachment_file_name
# => nil

Paperclip fails silently if imagemagick is not in PATH

Reported by Philip Hallstrom

Paperclip wasn't generating the thumbnails, but it would copy the original file into place. Worked on one host, not on another, same imagemagick version. When I ran the rake task to regenerate the thumbnails it worked.

Finally figured out that one host had a really small PATH environment that did not include /usr/local/bin (where convert/identify are).

Setting the correct path fixed the problem.

I'm not sure the best way to handle it, but a big note in the documentation or a check in Paperclip.run maybe to ensure that it can be found or some other error thrown.

I see in Paperclip.run where it is supposed to raise an error. I've double checked all my logs and see no mention of that string anywhere so it's getting eaten somewhere.

options[:whiny_thumbnails] = false doesn't run

Reported by Toni Reina

Hi,

At present, the option :whiny_thumbnails hasn't relevance. In a line 41 in attachment.rb, there are a @Whiny = options[:whiny_thumbnails] || options[:whiny] and how options[:whiny] by default is true, false || true = true.

Thanks

Cropping problems when config.cache_class = true

Reported by Giovanni Cangiani

I'm using rjcrop
to crop paperclip images. This worked great in Rails' 2.2.2 development environment, but as soon as I went into production mode, Paperclip didn't crop the images anymore.

This is what happens:

  @thing = Thing.find(1)
  @thing.update_attributes({:crop_x=>10, :crop_y=>20, :crop_w=>130, :crop_h=>85})
  @thing.paperclip_image.reprocess!

It seems that Paperclip doesn't recognize the change of these instance variables (they are not in the DB, the variables are being set through attr_accessor) and thus does not see a need to reprocess the images.

A solution I found is to set config.cache_classes = false in config/environments/production.rb (it defaults to true). Some links about similar problems can be found here.

Well, maybe this is something that can be solved, I'm not quite sure…

unexpected whiny_thumbnail behaviour

Reported by Edward Ocampo-Gooding

I’m using paperclip rev 28a8305 and running into some unexpected behaviour with regards to whiny_thumbnail:

When ImageMagick is not installed, and whiny_thumbnail is set to true, I expected to have an error raised during resizing, but instead get this when inspecting the model’s errors:

@errors={"screenshot"=>["/var/folders/Il/IlmxVjfXGIOwab7U1JE4-E+++TI/-Tmp-/stream.18183.0 is not recognized by the 'identify' command.", "/var/folders/Il/IlmxVjfXGIOwab7U1JE4-E+++TI/-Tmp-/stream.18183.0 is not recognized by the 'identify' command."]}

I added an assertion in my unit tests to look for this sort of thing and deal with it (spouting a message instructing the user to install ImageMagick), but I’d like to avoid this hack.

What do you say to patching this behaviour and making it more apparent and clear what has to be done to fix the error?

FloatDomainError (NaN)

I tried to upgrade from paperclip 2.1.2 to 2.2.8, and got this error:

FloatDomainError (NaN):
c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/geometry.rb:109:in %' c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/geometry.rb:109:incropping'
c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/geometry.rb:89:in transformation_to' c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/thumbnail.rb:63:intransformation_command'
c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/thumbnail.rb:47:in make' c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/processor.rb:32:inmake'
c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/attachment.rb:366:in post_process_styles' /vendor/rails/activerecord/lib/active_record/attribute_methods.rb:213:ininject'
c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/attachment.rb:365:in each' c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/attachment.rb:365:ininject'
c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/attachment.rb:365:in post_process_styles' c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/attachment.rb:362:ineach'
c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/attachment.rb:362:in post_process_styles' c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/attachment.rb:348:inpost_process'
c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip/attachment.rb:89:in assign' c:/ruby/lib/ruby/gems/1.8/gems/thoughtbot-paperclip-2.2.8/lib/paperclip.rb:204:inphoto='
/vendor/rails/activerecord/lib/active_record/base.rb:2462:in send' /vendor/rails/activerecord/lib/active_record/base.rb:2462:inupdate_attribute'
/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:214:in send' /vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:214:inmethod_missing'
/app/controllers/profiles_controller.rb:73:in pic' /vendor/rails/actionpack/lib/action_controller/base.rb:1256:insend'
/vendor/rails/actionpack/lib/action_controller/base.rb:1256:in perform_action_without_filters' /vendor/rails/actionpack/lib/action_controller/filters.rb:617:incall_filters'
/vendor/rails/actionpack/lib/action_controller/filters.rb:638:in run_before_filters' /app/controllers/application.rb:26:incall'
/app/controllers/application.rb:26
/vendor/rails/activesupport/lib/active_support/callbacks.rb:182:in call' /vendor/rails/activesupport/lib/active_support/callbacks.rb:182:inevaluate_method'
/vendor/rails/actionpack/lib/action_controller/filters.rb:184:in call' /vendor/rails/actionpack/lib/action_controller/filters.rb:635:inrun_before_filters'
/vendor/rails/actionpack/lib/action_controller/filters.rb:615:in call_filters' /vendor/rails/actionpack/lib/action_controller/filters.rb:610:inperform_action_without_benchmark'
/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in perform_action_without_rescue_without_instrument_41569710' c:/ruby/lib/ruby/1.8/benchmark.rb:293:inmeasure'
/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in perform_action_without_rescue_without_instrument_41569710' c:/ruby/lib/ruby/gems/1.8/gems/fiveruns-dash-ruby-0.8.8/lib/fiveruns/dash/instrument.rb:125:inperform_action_without_rescue'
/vendor/rails/actionpack/lib/action_controller/rescue.rb:136:in perform_action_without_caching' /vendor/rails/actionpack/lib/action_controller/caching/sql_cache.rb:13:inperform_action_without_instrument_41580570'
/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:34:in cache' /vendor/rails/activerecord/lib/active_record/query_cache.rb:8:incache'
/vendor/rails/actionpack/lib/action_controller/caching/sql_cache.rb:12:in perform_action_without_instrument_41580570' c:/ruby/lib/ruby/gems/1.8/gems/fiveruns-dash-ruby-0.8.8/lib/fiveruns/dash/instrument.rb:121:inperform_action_without_instrument_41577620'
c:/ruby/lib/ruby/gems/1.8/gems/fiveruns-dash-ruby-0.8.8/lib/fiveruns/dash/instrument.rb:65:in timing' c:/ruby/lib/ruby/gems/1.8/gems/fiveruns-dash-ruby-0.8.8/lib/fiveruns/dash/instrument.rb:120:inperform_action_without_instrument_41577620'
c:/ruby/lib/ruby/gems/1.8/gems/fiveruns-dash-ruby-0.8.8/lib/fiveruns/dash/instrument.rb:121:in perform_action_without_fiveruns_dash_context' c:/ruby/lib/ruby/gems/1.8/gems/fiveruns-dash-ruby-0.8.8/lib/fiveruns/dash/instrument.rb:65:intiming'
c:/ruby/lib/ruby/gems/1.8/gems/fiveruns-dash-ruby-0.8.8/lib/fiveruns/dash/instrument.rb:120:in perform_action_without_fiveruns_dash_context' c:/ruby/lib/ruby/gems/1.8/gems/fiveruns-dash-rails-0.7.8/lib/fiveruns/dash/rails.rb:194:inperform_action_without_dash_startup'
c:/ruby/lib/ruby/gems/1.8/gems/fiveruns-dash-rails-0.7.8/lib/fiveruns/dash/recipes/rails.rb:113:in perform_action' /vendor/rails/actionpack/lib/action_controller/base.rb:524:insend'
/vendor/rails/actionpack/lib/action_controller/base.rb:524:in process_without_filters' /vendor/rails/actionpack/lib/action_controller/filters.rb:606:inprocess_without_session_management_support'
/vendor/rails/actionpack/lib/action_controller/session_management.rb:134:in process' /vendor/rails/actionpack/lib/action_controller/base.rb:392:inprocess_without_fiveruns_dash_tracing'
c:/ruby/lib/ruby/gems/1.8/gems/fiveruns-dash-rails-0.7.8/lib/fiveruns/dash/rails.rb:172:in process' c:/ruby/lib/ruby/gems/1.8/gems/fiveruns-dash-rails-0.7.8/lib/fiveruns/dash/rails.rb:183:incall'
c:/ruby/lib/ruby/gems/1.8/gems/fiveruns-dash-rails-0.7.8/lib/fiveruns/dash/rails.rb:183:in process' /vendor/rails/actionpack/lib/action_controller/dispatcher.rb:184:inhandle_request'
/vendor/rails/actionpack/lib/action_controller/dispatcher.rb:112:in dispatch_unlocked' /vendor/rails/actionpack/lib/action_controller/dispatcher.rb:125:indispatch'
/vendor/rails/actionpack/lib/action_controller/dispatcher.rb:124:in synchronize' /vendor/rails/actionpack/lib/action_controller/dispatcher.rb:124:indispatch'
/vendor/rails/actionpack/lib/action_controller/dispatcher.rb:134:in dispatch_cgi' /vendor/rails/actionpack/lib/action_controller/dispatcher.rb:41:indispatch'
c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/bin/../lib/mongrel/rails.rb:76:in process' c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/bin/../lib/mongrel/rails.rb:74:insynchronize'
c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/bin/../lib/mongrel/rails.rb:74:in process' c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel.rb:159:inprocess_client'
c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel.rb:158:in each' c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel.rb:158:inprocess_client'
c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel.rb:285:in run' c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel.rb:285:ininitialize'
c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel.rb:285:in new' c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel.rb:285:inrun'
c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel.rb:268:in initialize' c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel.rb:268:innew'
c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel.rb:268:in run' c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel/configurator.rb:282:inrun'
c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel/configurator.rb:281:in each' c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel/configurator.rb:281:inrun'
c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/bin/mongrel_rails:128:in run' c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/lib/mongrel/command.rb:212:inrun'
c:/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.5-x86-mswin32-60/bin/mongrel_rails:281
/vendor/rails/activesupport/lib/active_support/dependencies.rb:142:in load_without_new_constant_marking' /vendor/rails/activesupport/lib/active_support/dependencies.rb:142:inload'
/vendor/rails/activesupport/lib/active_support/dependencies.rb:521:in new_constants_in' /vendor/rails/activesupport/lib/active_support/dependencies.rb:142:inload'
/vendor/rails/railties/lib/commands/servers/mongrel.rb:64
c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in gem_original_require' c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:inrequire'
/vendor/rails/activesupport/lib/active_support/dependencies.rb:153:in require' /vendor/rails/activesupport/lib/active_support/dependencies.rb:521:innew_constants_in'
/vendor/rails/activesupport/lib/active_support/dependencies.rb:153:in require' /vendor/rails/railties/lib/commands/server.rb:49 c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:ingem_original_require'
c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
script/server:3

Paperclip not saving uploaded files

When uploading a photo for a model with paperclip, everything would act like it was working properly including no errors in the log files. I had used the following initialization configuration

Paperclip.options[:command_path] = "/opt/local/bin"
Paperclip.options[:whiny_thumbnails] = true
Paperclip.options[:log] = true

and here is the relevant section of the 'working' logs.

[paperclip] Paperclip attachment photo on Staff initialized.
[paperclip] Assigning # to photo
[paperclip] Writing attributes for photo
[paperclip] Post-processing photo
[paperclip] Processing thumb # in the thumbnail processor.
[paperclip] Processing large # in the thumbnail processor.

Everything would look like it was working fine but no files where saved or created where they should have been. After some messing around I decided to symlink the composite, identify and convert binaries to /usr/bin from the configured macports directory and comment out the command_path option in the initializer. This seems to have fixed the problem as files are now created and displayed properly.

Is this a bug in using command_path or is there another issue? This is on OS X 10.5 using apache+passenger and macports to install imagemagick

This was using paperclip 2.2.8 and I had defined the command path in config/initializers/paperclip.rb

undefined method `exitstatus' for nil:NilClass

Paperclip 2.2.8 works fine with my app on linux (Ubuntu 8.0.4) but when I try to run my app on Windows (that has ImageMagick 6.5.2 Q16) Paperclip tanks. Initially it was giving me the error this guy was getting, http://bit.ly/14PPyS, but after applying his fix I started getting a new error.

undefined method `exitstatus' for nil:NilClass

I ran "rake test" inside the gem dir on linux and windows, and on windows it had 3 errors and 1 failure.

  1. Error:
    A multipage PDF being thumbnailed at 100x100 with cropping should create the thumbnail when sent #make. Paperclip::NotIdentifiedByImageMagickError: ./test/fixtures/twopage.pdf is not recognized by the `identify' command.

  2. Error:
    A multipage PDF being thumbnailed at 100x100 with cropping should report its current and target geometries. Paperclip::NotIdentifiedByImageMagickError: ./test/fixtures/twopage.pdf is not recognized by the `identify' command.

  3. Error:
    A multipage PDF being thumbnailed at 100x100 with cropping should report its correct format. Paperclip::NotIdentifiedByImageMagickError: ./test/fixtures/twopage.pdf is not recognized by the `identify' command.

  4. Failure:
    A multipage PDF should start with two pages with dimensions 612x792.
    ("612x792612x792") expected but was
    ("")

Tests pass fine on osx and ubuntu.

bad return path when styles coercing image mime types

When using paperclip has_attachment on a model and the mime type of the original image is coerced into something else using :styles and the default style is changed from :original to some else, the resulting path returns the incorrect file type by using the original mime type.

For instance

has_attached_file :image,
                    :styles => {:thumb=> ["100x100#", :jpg],
                                :small  => ["150x150>", :jpg],
                                :medium => ["300x300>", :jpg],
                                :large => ["500x500>", :jpg]
                                },
                   :default_style => :large

If the original file was .png a call to model.image.path will return the .png extension even though the default style is now :large which is of type .jpg

I have attached a failing integration test case and the fix: http://gist.github.com/124457

Thanks for the great plug-in!

class_caching && proc arguments to has_attached_file

When class_caching is enabled (default production configuration) and has_attached_file is called with proc values for styles hash keys :processors, :geometry, those lambdas are called only once because of:

def solidify_style_definitions #:nodoc:
  @styles.each do |name, args|
    @styles[name][:geometry] = @styles[name][:geometry].call(instance) if @styles[name][:geometry].respond_to?(:call)
    @styles[name][:processors] = @styles[name][:processors].call(instance) if @styles[name][:processors].respond_to?(:call)
  end
end

Suggestion is to make the following replacement in attachment.rb

def initialize ...
...
@Styles = options[:styles] => @Styles = options[:styles].clone
...
end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.