Carrierwave Reset after Reboot - ruby-on-rails

Both the app and db (mongodb) servers were rebooted last night. All carrierwave mounted uploaders are returning the default images for avatars, even though the files still exist.
I am using fog storage on Rackspace CDN. Each user model contains a field of avatar_filename. I tried running user.avatar.recreate_versions! however that errors out due to nil.
Is there any way to restore my images (they still exist!) and prevent this from happening again? I have searched around but it doesn't look like this is a common prom.
In my user model:
# Avatar
mount_uploader :avatar, AvatarUploader
AvatarUploader:
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :fog
def default_url
"/assets/users/profile-default_#{version_name}.png"
end
# Large
version :large do
resize_to_limit(600, 600)
end
# Small
version :small do
process :crop
resize_to_fill(140, 140)
end
# Thumbnail
version :thumb, :from_version => :small do
resize_to_fill(35, 35)
end
def extension_white_list
%w(jpg jpeg png)
end
def filename
if #filename_created
#filename_created
elsif original_filename
#name ||= Digest::MD5.hexdigest(File.dirname(current_path))
#filename_created = "a_#{timestamp}_#{#name}.#{file.extension}"
#filename_created
end
end
def timestamp
var = :"##{mounted_as}_timestamp"
model.instance_variable_get(var) or model.instance_variable_set(var, Time.now.to_i)
end
def crop
if model.crop_x.present?
resize_to_limit(600, 600)
manipulate! do |img|
x = model.crop_x.to_i
y = model.crop_y.to_i
w = model.crop_w.to_i
h = model.crop_h.to_i
img.crop!(x, y, w, h)
end
end
end
end

Given that the images are there, you could reupload them as remote files with user.remote_avatar_url = "the url for this avatar"
To avoid this in the future you have to keep in mind how you are processing the file name. That process is reapplied each time you do recreate_versions!. Put this code in your uploader to get around this:
class AvatarUploader < CarrierWave::Uploader::Base
def filename
if original_filename
if model && model.read_attribute(:avatar).present?
model.read_attribute(:avatar)
else
# new filename
end
end
end
end
You can find more information about this in the following wiki article: https://github.com/jnicklas/carrierwave/wiki/How-to%3A-Create-random-and-unique-filenames-for-all-versioned-files

Related

CarrierWave version path

I have model Catagory
class Category < ActiveRecord::Base
mount_uploader :image, CategoryImageUploader
end
I need to save the image with the name (id saved category)
class CategoryImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :file
mounted:
def store_dir
#"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def store_path(for_file = filename)
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}/#{for_file}"
end
version :small do
process resize_to_fit: [48, 48]
def filename(uploaded_file = file)
if uploaded_file.present?
"small_#{model.id}.#{uploaded_file.extension}"
end
end
end
version :big do
process resize_to_fit: [200, 200]
def filename(uploaded_file = file)
if uploaded_file.present?
"big_#{model.id}.#{uploaded_file.extension}"
end
end
end
def filename(uploaded_file = file)
if uploaded_file.present?
"#{model.id}.#{uploaded_file.extension}"
end
end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
end
I'm use https://coderwall.com/p/mulldw/custom-file-names-with-carrierwave-and-amazon-s3 to save image like this 3.png 4.png
version :small and version :big aslo save (like big_3.png small_3.png )
but
**Category.last.image_url => "/uploads/category/image/10/10.png"
Category.last.image_url(:small) = > "/uploads/category/image/10/10.png"
Category.last.image_url(:big) = > "/uploads/category/image/10/10.png"**
All links lead to one image 10.png
I need
**Category.last.image_url => "/uploads/category/image/10/10.png"
Category.last.image_url(:small) = > "/uploads/category/image/10/small_10.png"
Category.last.image_url(:big) = > "/uploads/category/image/10/big_10.png"**

Rails 4 Carrierwave + Minimagick: Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: `mogrify -crop

Been researching around but fail to pinpoint the problem: I am following Railscasts PRO #182 on cropping images using JCrop, Carrierwave and Minimagick. As I come to recreating image versions I am prompted the error:
CarrierWave::ProcessingError (Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: mogrify -crop! 250x250+531+32 /tmp/mini_magick20160108-6544-1ec50pf.png failed with error:
mogrify: unrecognized option -crop!' # error/mogrify.c/MogrifyImageCommand/4197.
):
app/uploaders/image_uploader.rb:48:incrop'
app/models/course.rb:15:in crop_image'
app/controllers/courses_controller.rb:12:inupdate'
Can somebody help me understand what this error is indicating?
Model
class Course < ActiveRecord::Base
attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
after_update :crop_image
mount_uploader :image, ImageUploader
def crop_image
image.recreate_versions! if crop_x.present?
end
end
Controller
class CoursesController < ApplicationController
def update
#course = Course.find(params[:id])
if #course.update_attributes(course_params)
if course_params[:image].present?
render :crop
else
redirect_to #course, notice: 'Successfully updated'
end
end
end
def course_params
params.require(:course).permit(:title, :image, :crop_x, :crop_y, :crop_w, :crop_h)
end
end
ImageUploader
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :thumb do
process :crop
process :resize_to_fit => [250, 250]
end
def crop
if model.crop_x.present?
resize_to_fit(800, 350)
manipulate! do |img|
x = model.crop_x.to_i
y = model.crop_y.to_i
w = model.crop_w.to_i
h = model.crop_h.to_i
img.crop!("#{w}x#{h}+#{x}+#{y}")
end
end
end
end
Turns out the option -crop! does not exist in command mogrify. The resolution is simply changing .crop! to .crop
i.e. Within ImageUploader:
img.crop!("#{w}x#{h}+#{x}+#{y}") --> img.crop("#{w}x#{h}+#{x}+#{y}")
Having same issue with strip. Only happens when images are large.
First issue of this was in 2012 and was closed without a great solution.

set content_type and extension with carrierwave depending on its contents

I hava a uploader for pdf documents. After, uploader have a method to create an thumb image of pdf file.
This is the uploader:
require 'carrierwave/processing/mime_types'
class DocumentUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
include Sprockets::Helpers::RailsHelper
include Sprockets::Helpers::IsolatedHelper
include CarrierWave::MimeTypes
IMAGE_EXTENSIONS = %w(png)
DOCUMENT_EXTENSIONS = %w(pdf)
storage :fog
def store_dir
"documents/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def extension_white_list
IMAGE_EXTENSIONS + DOCUMENT_EXTENSIONS
end
# create a new "process_extensions" method. It is like "process", except
# it takes an array of extensions as the first parameter, and registers
# a trampoline method which checks the extension before invocation
def self.process_extensions(*args)
extensions = args.shift
args.each do |arg|
if arg.is_a?(Hash)
arg.each do |method, args|
processors.push([:process_trampoline, [extensions, method, args]])
end
else
processors.push([:process_trampoline, [extensions, arg, []]])
end
end
end
# our trampoline method which only performs processing if the extension matches
def process_trampoline(extensions, method, args)
extension = File.extname(original_filename).downcase
extension = extension[1..-1] if extension[0,1] == '.'
self.send(method, *args) if extensions.include?(extension)
end
def cover
manipulate! do |frame, index|
frame if index.zero?
end
end
version :thumb do
process :cover
#process :resize_to_limit => [110, 60]
process_extensions IMAGE_EXTENSIONS, :resize_to_fit => [110, 60]
process :convert => 'png'
end
process :set_content_type
process :save_content_type_and_size_in_model
def save_content_type_and_size_in_model
model.content_type = file.content_type if file.content_type
model.file_size = file.size
end
end
However when I see the files (both, pdf and thumb image) inside of amazon s3, the extension for thumbnail is .pdf instead of .png:
How can I change the pdf extension to .png and content_type of thumb image?
This works for me to set the extension:
version :thumb do
process :resize_to_fit => [150, 150]
process :convert => 'png'
def full_filename (for_file = model.source.file)
super.chomp(File.extname(super)) + '.png'
end
end

Carrierwave not utilizing default_url when version not present

Essentially, the photo_url(:thumb) displays the intended thumb url even though the file doesn't physically exist.
# encoding: utf-8
class WinePhotoUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
# So the :thumb will be stored in "public/assets/wines/thumb/2008-meritage-750mL.jpg" for example.
def store_dir
"assets/wines/#{version_name}"
end
def cache_dir
Rails.root.join 'tmp/uploads'
end
CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
# If no version name is present (original), just provide the thumb path
# This method is never called!!! Why not?
def default_url
ActionController::Base.helpers.asset_path("pages/wines/#{version_name || :thumb}/default.png")
end
# To save disk space, make sure the original image is no larger than the croppable + a few pixels
process :resize_to_fit => [2000, 2000]
version :croppable, :if => :not_cropping? do
process :common
process :resize_and_pad => [1200, 1200, :white]
process :convert => "jpg"
# Override the default naming convention...I store in folders,
# so I don't want the version prepended to the file name.
def full_filename(for_file = model.photo.file)
the_filename
end
end
version :show, :if => :not_cropping? do
process :resize_to_show
process :convert => "jpg"
def full_filename(for_file = model.photo.file)
the_filename
end
end
version :thumb, :from_version => :croppable, :if => :viewing_or_cropping? do
process :custom_thumbnail => [200, 200]
def full_filename(for_file = model.photo.file)
the_filename
end
end
def common(q=100, s='1.2x1+0.75+0.05')
manipulate! do |img|
img.combine_options do |i|
i.quality q
i.antialias
i.background :white
i.flatten
i.density 72
i.profile "#{Rails.root}/lib/color_profiles/sRGB_v4_ICC_preference_displayclass.icc"
i.strip
end
img = yield(img) if block_given?
img.combine_options do |i|
i.unsharp s
end
img
end
end
def resize_to_show
common do |img|
img.combine_options do |i|
i.trim
i.thumbnail 110
i.background :white
i.gravity :center
i.extent 170
end
img
end
end
def custom_thumbnail(width, height)
manipulate! do |img|
img.combine_options do |i|
i.distort :srt, "#{model.crop_x},#{model.crop_y} 1 -30 600,600"
i.repage.+
i.gravity :center
i.crop "#{model.crop_w}x#{model.crop_h}+0+0"
i.repage.+
i.thumbnail "#{width}x#{height}"
i.unsharp '1.2x1+0.75+0.05'
end
img
end
end
def not_cropping? picture
!model.cropping?
end
# For some stupid reason, if I only check for 'model.cropping?' and
# it returns false, the photo_url(:thumb) will always show the default_url
# and never show the actual url! This is terrible logic. The version declarations
# above should only affect the generation of thumbnails, not whether the call
# to photo_url(:thumb) works.
def viewing_or_cropping? picture
model.cropping? or model.changes.merge(model.previous_changes).empty?
end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_white_list
%w(jpg jpeg gif png tif tiff)
end
# Only modify the version names, not the original uploaded file name
def filename
"#{ model.get_permalink(:normalized => true) }#{ File.extname original_filename }" if original_filename
end
# The filename should be the wine's permalink name (ex., 2008-merlot-reserve-750mL.jpg)
def the_filename
"#{ model.get_permalink(:normalized => true) }.jpg"
end
# Remove this when https://github.com/carrierwaveuploader/carrierwave/issues/1164 is solved.
def recreate_versions!(*versions)
if versions.any?
from_versions = versions.group_by { |v| self.class.versions[v][:options][:from_version] }
from_versions.each do |from, versions|
next if from.nil?
file = CarrierWave::SanitizedFile.new(self.versions[from.to_sym].file)
store_versions!(file, versions)
end
else
super(*versions)
end
end
end
So a call to #wine.photo_url(:thumb) produces
http://dev.mydomain.com/assets/wines/thumb/2006-cabernet-sauvignon-750mL.jpg
when it should be producing
http://dev.mydomain.com/assets/pages/wines/thumb/default.png
because the file doesn't exist.
My best guess is that Carrierwave generates the file names based on the existence of the model's attribute in the database and not whether or not the specific version of the file exists. Not what I was expecting from default_url but it still makes sense in its limited way.

Resize images with carrierwave if it exceeds height/width

I have looked around and could not find a solution after I tried to do it on my own. When users upload photos, I want for them to be resized if it exceeds my minimum and max dimensions. However I would like two conditionals. The photos that were taken sideways (East/West) should remain within the dimensions I set, and the same follows for the photos taken the tall way (North/South).
For example is a user uploads a photo that's standing the long way and has dimensions of 3264x1840. The upload should be resized to fit 584x329. If the upload is less than 584x329 then it will not adjust the size.
The other example is if user uploads a photo that was taken the tall way and it had dimensions of 2448 x 3264. The upload should be resized to fit 247x329.
I was trying to use MiniMagick with this as I believe that would be the requirement. If I can only use CarrierWave then that's perfect, but I thought MiniMagick was supposed to be used for resizing photos.
The error I receive is 'undefined method resize' for #<ImageUploader:0x007f8606feb9b8>' and it points to#photo = Photo.new(params[:photo])` from def create in the controller.
BTW dimensions are high because those are normally your phones default sizes when you upload a photo.
image_uploader.rb:
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
process :resize => [584, 329]
def resize_to_limit(width, height)
manipulate! do |img|
img.resize "#{width}x#{height}>"
img = yield(img) if block_given?
img
end
end
# Create different versions of your uploaded files:
version :thumb do
process :resize_to_limit => [200, 200]
end
end
Photos Controller:
def create
#photo = Photo.new(params[:photo])
#photo.user = current_user
if #photo.save
flash[:notice] = "Successfully created photos."
redirect_to :back
else
render :action => 'new'
end
end
def resize(width, height, gravity = 'Center')
manipulate! do |img|
img.combine_options do |cmd|
cmd.resize "#{width}"
if img[:width] < img[:height]
cmd.gravity gravity
cmd.background "rgba(255,255,255,0.0)"
cmd.extent "#{width}x#{height}"
end
end
img = yield(img) if block_given?
img
end
end
Change :resize in the image uploader to process :resize_to_fit => [584, 329]

Resources