I have similar models as described in RailsCasts:
app/models/resident.rb:
class Resident < ActiveRecord::Base
include PhotoConcern
end
app/models/employee.rb:
class Employee < ActiveRecord::Base
include PhotoConcern
end
app/models/concerns/photo_concern.rb:
module PhotoConcern
extend ActiveSupport::Concern
included do
mount_uploader :photo, PhotoUploader
attr_accessor :photo_crop_x, :photo_crop_y, :photo_crop_w, :photo_crop_h
after_save :crop_photo
def crop_photo
photo.recreate_versions! if photo_crop_x.present?
end
end
end
app/uploaders/photo_uploader.rb:
class PhotoUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :cropped do
process :crop
end
version :thumb, from_version: :cropped do
process resize_to_fill: [100, 100]
end
version :avatar, from_version: :cropped do
process resize_to_fill: [200, 200]
end
def crop
return if model.photo_crop_x.blank?
resize_to_limit(500, nil)
resize_to_fit(500, nil)
manipulate! do |img|
size = model.photo_crop_w << 'x' << model.photo_crop_h
offset = '+' << model.photo_crop_x << '+' << model.photo_crop_y
img.crop("#{size}#{offset}")
img
end
end
end
app/views/employees/show.slim
= image_tag (@employee.photo.present? ? @employee.photo.url(:avatar) : "client_#{@employee.sex}.png"), class: 'img-circle img-responsive'
I want to rename version files after cropping so my users don't struggle with a cache. It's described in CarrierWave wiki how to rename files but also it's written "In order to save the newly generated filename you have to call save! on the model after recreate_versions!".
How can I rename version files? I can't call save!
in my Employee's after_save
again because there are more hooks that shouldn't be called twice. Also, PhotoConcern is included into another class.
Related wiki articles:
In order to save the newly generated filename you have to call save! on the model after recreate_versions!.
So I believe the answer to your doubts is included in the Carrierwave rubydocumentation
recreate_versions!(*versions) ⇒ Object
Recreate versions and reprocess them. This can be used to recreate versions if their parameters somehow have changed.
This method will store the *versions
if they are not ommitted, otherwise the cached file
will be stored.
# File 'lib/carrierwave/uploader/versions.rb', line 216
def recreate_versions!(*versions)
# Some files could possibly not be stored on the local disk. This
# doesn't play nicely with processing. Make sure that we're only
# processing a cached file
#
# The call to store! will trigger the necessary callbacks to both
# process this version and all sub-versions
if versions.any?
file = sanitized_file if !cached?
# the file will be stored
store_versions!(file, versions)
else
cache! if !cached?
# If new_file is omitted, a previously cached file will be stored.
store!
end
What does store!
do?
This is the rubydoc page about store!
store!(new_file = nil) ⇒ Object
Stores the file by passing it to this Uploader's storage engine. If new_file is omitted, a previously cached file will be stored
This method is included in your class PhotoUploader < CarrierWave::Uploader::Base
and it uses with_callbacks
to store your file using the callback :store
. The callback triggers this method.
# File 'lib/carrierwave/uploader/store.rb', line 53
def store!(new_file=nil)
cache!(new_file) if new_file && ((@cache_id != parent_cache_id) || @cache_id.nil?)
if !cache_only and @file and @cache_id
with_callbacks(:store, new_file) do
new_file = storage.store!(@file)
if delete_tmp_file_after_storage
@file.delete unless move_to_store
cache_storage.delete_dir!(cache_path(nil))
end
@file = new_file
@cache_id = nil
end
end
end
What does store_versions!
method do?
def store_versions!(new_file, versions=nil)
if versions
active = Hash[active_versions]
versions.each { |v| active[v].try(:store!, new_file) } unless active.empty?
else
active_versions.each { |name, v| v.store!(new_file) }
end
end
What are the Carrierwave callbacks and how to use them?
after :store, :store_versions!
This question on SO explains and the wiki explain how callbacks work, by doing after :store, :my_method
inside your version :low do
block, you will execute my_method
only on after :store
callback (only for that version).
The :store
callback corresponds to the execution of store!
.
And what is the @filename
attribute? How does recreate_versions!
encode the filename?
@filename
is defined with method filename
in lib/carrierwave/uploader/store.rb
##
# Override this in your Uploader to change the filename.
#
# Be careful using record ids as filenames. If the filename is stored in the database
# the record id will be nil when the filename is set. Don't use record ids unless you
# understand this limitation.
#
# Do not use the version_name in the filename, as it will prevent versions from being
# loaded correctly.
#
# === Returns
#
# [String] a filename
#
def filename
@filename
end
The guide from carrierwave suggest to use def filename
to recreate unique filenames when recreating versions with recreate_version!
.
This method does not save to the Database, to save to the database you need to calle save!
on the appropriata Carrierwave
callbacks, without breaking you Carrierwave
GEM
I don't have the solution to this issue, but there is no documentation on this and we should start building it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With