Paperclip model which checks an upload (its temp file) whether it's an animated GIF. If so it sets attachment_is_animated
in the db to true. But, because this job needs to go into the background (DelayedJob), the temp file is probably gone by the time it's needed, which is most likely what's causing the InfiniteInterpolationError
.
Live app which you can run on the fly: http://runnable.com/VXMNrsiY_6Fd-YRn/paperclip-delayedjob-infiniteinterpolationerror (remember to run bin/delayed_job start
before hitting the big green Run button)
app/models/photo.rb
class Photo < ActiveRecord::Base
belongs_to :post, class_name: "Forem::Post"
attr_accessor :applicable_styles
has_attached_file :attachment, styles: lambda {
|attachment| attachment.instance.applicable_styles
}
before_post_process :setup_styles
before_save :set_attachment_is_animated
##########
# START DELAYED PAPERCLIP
process_in_background :attachment
# Fix conditional styles not being set up in time for `process_in_background`
def applicable_styles
@applicable_styles || setup_styles
end
##########
validates_attachment :attachment, presence: true, content_type: {
content_type: ["image/jpg", "image/jpeg", "image/png", "image/gif", "video/mp4"]
}
def attachment_url(style = :medium)
setup_styles
style = is_animated_gif? ? "#{style.to_s}_animated".to_sym : style
attachment.url(style)
end
def setup_styles
@applicable_styles ||= {}
if is_animated_gif?
# Convert animated GIF to MP4
@applicable_styles[:medium_animated] = {
format: "mp4",
streaming: true,
processors: [:ffmpeg, :qtfaststart]
}
@applicable_styles[:thumbnail_animated] = {
format: "png",
time: 0.1,
processors: [:ffmpeg]
}
else
# Process as regular photos
@applicable_styles[:medium] = "480x"
@applicable_styles[:thumbnail] = "50x50#"
end
@applicable_styles
end
private
def is_animated_gif?
attachment_path = attachment.queued_for_write[:original] ? attachment.queued_for_write[:original].path : attachment.path
rmagick = Magick::ImageList.new(attachment_path)
attachment.content_type =~ /gif/ && rmagick.scene > 1
end
def set_attachment_is_animated
self.attachment_is_animated = is_animated_gif?
end
end
irb(main):001:0> Delayed::Job.all
irb(main):002:0> Delayed::Job.find("1").last_error
Paperclip::Errors::InfiniteInterpolationError
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:53:in `url'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:34:in `block (2 levels) in interpolate'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:33:in `gsub'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:33:in `block in interpolate'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:32:in `each'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:32:in `inject'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:32:in `interpolate'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/attachment.rb:546:in `interpolate'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/attachment.rb:166:in `path'
/usr/home/myapp/app/models/photo.rb:58:in `is_animated_gif?'
/usr/home/myapp/app/models/photo.rb:36:in `setup_styles'
/usr/home/myapp/app/models/photo.rb:6:in `applicable_styles'
/usr/home/myapp/app/models/photo.rb:10:in `block in <class:Photo>'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/attachment.rb:200:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/attachment.rb:200:in `styles'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:100:in `extension'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:45:in `filename'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:34:in `block (2 levels) in interpolate'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:33:in `gsub'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:33:in `block in interpolate'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:32:in `each'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:32:in `inject'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:32:in `interpolate'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_paperclip-2.9.1/lib/delayed_paperclip/url_generator.rb:16:in `for_with_processed'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/attachment.rb:143:in `url'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:54:in `url'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:34:in `block (2 levels) in interpolate'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:33:in `gsub'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:33:in `block in interpolate'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:32:in `each'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:32:in `inject'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/interpolations.rb:32:in `interpolate'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/attachment.rb:546:in `interpolate'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/attachment.rb:166:in `path'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/storage/filesystem.rb:85:in `copy_to_local_file'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/io_adapters/attachment_adapter.rb:27:in `copy_to_tempfile'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/io_adapters/attachment_adapter.rb:19:in `cache_current_values'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/io_adapters/attachment_adapter.rb:11:in `initialize'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/io_adapters/registry.rb:29:in `new'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/io_adapters/registry.rb:29:in `for'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/attachment.rb:97:in `assign'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/paperclip-4.2.1/lib/paperclip/attachment.rb:337:in `reprocess!'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_paperclip-2.9.1/lib/delayed_paperclip/attachment.rb:62:in `process_delayed!'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_paperclip-2.9.1/lib/delayed_paperclip.rb:36:in `process_job'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_paperclip-2.9.1/lib/delayed_paperclip/jobs/active_job.rb:12:in `perform'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activejob-4.2.0/lib/active_job/execution.rb:32:in `block in perform_now'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/callbacks.rb:117:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/callbacks.rb:117:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/callbacks.rb:338:in `block (2 levels) in simple'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activejob-4.2.0/lib/active_job/logging.rb:23:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activejob-4.2.0/lib/active_job/logging.rb:23:in `block (4 levels) in <module:Logging>'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/notifications.rb:164:in `block in instrument'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/notifications.rb:164:in `instrument'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activejob-4.2.0/lib/active_job/logging.rb:22:in `block (3 levels) in <module:Logging>'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activejob-4.2.0/lib/active_job/logging.rb:43:in `block in tag_logger'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/tagged_logging.rb:68:in `block in tagged'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/tagged_logging.rb:26:in `tagged'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/tagged_logging.rb:68:in `tagged'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activejob-4.2.0/lib/active_job/logging.rb:43:in `tag_logger'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activejob-4.2.0/lib/active_job/logging.rb:19:in `block (2 levels) in <module:Logging>'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/callbacks.rb:436:in `instance_exec'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/callbacks.rb:436:in `block in make_lambda'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/callbacks.rb:337:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/callbacks.rb:337:in `block in simple'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/callbacks.rb:92:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/callbacks.rb:92:in `_run_callbacks'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/callbacks.rb:734:in `_run_perform_callbacks'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/callbacks.rb:81:in `run_callbacks'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activejob-4.2.0/lib/active_job/execution.rb:31:in `perform_now'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activejob-4.2.0/lib/active_job/execution.rb:21:in `execute'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/activejob-4.2.0/lib/active_job/queue_adapters/delayed_job_adapter.rb:34:in `perform'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/backend/base.rb:94:in `block in invoke_job'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `block in initialize'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `execute'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:40:in `run_callbacks'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/backend/base.rb:91:in `invoke_job'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:204:in `block (2 levels) in run'
/usr/local/lib/ruby/2.2.0/timeout.rb:89:in `block in timeout'
/usr/local/lib/ruby/2.2.0/timeout.rb:99:in `call'
/usr/local/lib/ruby/2.2.0/timeout.rb:99:in `timeout'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:204:in `block in run'
/usr/local/lib/ruby/2.2.0/benchmark.rb:303:in `realtime'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:203:in `run'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:280:in `block in reserve_and_run_one_job'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `block in initialize'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `execute'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:40:in `run_callbacks'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:280:in `reserve_and_run_one_job'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:187:in `block in work_off'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:186:in `times'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:186:in `work_off'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:150:in `block (4 levels) in start'
/usr/local/lib/ruby/2.2.0/benchmark.rb:303:in `realtime'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:149:in `block (3 levels) in start'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `block in initialize'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `execute'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:40:in `run_callbacks'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:148:in `block (2 levels) in start'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:147:in `loop'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:147:in `block in start'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/plugins/clear_locks.rb:7:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/plugins/clear_locks.rb:7:in `block (2 levels) in <class:ClearLocks>'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:79:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:79:in `block (2 levels) in add'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:61:in `block in initialize'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:79:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:79:in `block in add'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:66:in `execute'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/lifecycle.rb:40:in `run_callbacks'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/worker.rb:146:in `start'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/command.rb:124:in `run'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/command.rb:112:in `block in run_process'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/daemons-1.2.2/lib/daemons/application.rb:265:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/daemons-1.2.2/lib/daemons/application.rb:265:in `block in start_proc'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/daemons-1.2.2/lib/daemons/daemonize.rb:84:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/daemons-1.2.2/lib/daemons/daemonize.rb:84:in `call_as_daemon'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/daemons-1.2.2/lib/daemons/application.rb:269:in `start_proc'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/daemons-1.2.2/lib/daemons/application.rb:295:in `start'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/daemons-1.2.2/lib/daemons/controller.rb:56:in `run'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/daemons-1.2.2/lib/daemons.rb:193:in `block in run_proc'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/daemons-1.2.2/lib/daemons/cmdline.rb:88:in `call'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/daemons-1.2.2/lib/daemons/cmdline.rb:88:in `catch_exceptions'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/daemons-1.2.2/lib/daemons.rb:192:in `run_proc'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/command.rb:110:in `run_process'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/command.rb:91:in `block in daemonize'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/command.rb:89:in `times'
/usr/home/myapp/vendor/bundle/ruby/2.2.0/gems/delayed_job-4.0.6/lib/delayed/command.rb:89:in `daemonize'
bin/delayed_job:5:in `<main>'"