I was using the Paperclip gem: https://github.com/thoughtbot/paperclip
I'm now using Carrierwave: https://github.com/carrierwaveuploader/carrierwave
My production website is currently using Paperclip. I'm going to be updating the production website to use Carrierwave.
The folder structure for uploads in Paperclip differs from Carrierwave.
I'm also using Amazon S3 to store uploads.
I'm wondering if there's a way to convert my production files uploaded with Paperclip to Carrierwave.
For example, with Paperclip in production I currently have something like the following for resumes:
bucket_name/model_name/resume/000/000/model_id/original/test.pdf
With Carrierwave it should be:
bucket_name/uploads/model_name/resume/model_id/original/test.pdf
Right now it seems I have to make this conversion manually. I was wondering if there's a better approach.
Please advise.
The CarrierWave::Compatibility::Paperclip module already provides this functionality. Just do the following in your uploader:
class MyUploader < CarrierWave::Uploader::Base
include CarrierWave::Compatibility::Paperclip
# The :id_partition symbol will trigger a proc in the Paperclip compatibility module that will build out the properly partition directory structure
def store_dir
"#{model.class.to_s.underscore}/#{mounted_as.to_s}/:id_partition"
end
end
Have you tried changing the store_dir options define in carrierwave uploader to look exactly like that of paperclip
def store_dir
"#{model.class.to_s.underscore}/resume/#{id_partitioning}/original/"
end
def id_partitioning
("%09d" % model.id).scan(/.{3}/).join("/")
end
Note : I just done remember how the paperclip does the id_partitioning (how much '0' it pad to the left based on object id )
but based upon your format 000/000/model_id look to me like 9 character Please confirm
Hope this help
Related
I am using CarrierWave with fog to upload my images to S3.
I have model Image that can represent images of different sizes and according to that needs to be saved in different folder.
For example, for image.jpg I could have two different uploaded versions that need to be saved as:
'images/large/image.jpg'
'images/small/image.jpg'
There could be arbitrary number of use cases and versions using minimagick can't cover them all.
So far I haven't been able to find solution. Does anyone know how to do this?
I've seen this question asked a few times so I'll write what my final solution is.
Instead of defining mount_uploader on model I decided to just use Uploader independently and save urls to records later.
Dynamically changing store_dir and filename can be accomplished like this
uploader = Uploader.new
uploader.define_singleton_method(:store_dir) do
'new_store_dir'
end
uploader.define_singleton_method(:filename) do
'new_filename'
end
uploader.store!(image)
Using this approach you can also define names with local variables or whatever you have available in controller.
Hopefully it helps someone else as well.
in order to change where uploaded files are put, just override the store_dir method:, for your case (reference link)
class Image < CarrierWave::Uploader::Base
storage :file
# this if you using use condition for folder location
def store_dir
if model.somefield == "somecondition
"uploads/#{model.somefield}"
elsif model.somefield == "somecondition
"uploads/location2"
else
"uploads/default_dir"
end
end
# this is if you want to use version_name
def store_dir
'images/#{version_name}/'
end
end
I am using globalize gem for some locales.
I have added a field in translation that saves different image for different locales.
Rails admin globalize field only supports for string and it doesn't provide any option to upload a file.
How can I achieve this option?
For uploads you must use some processing method to allow storing your file under a simple string field.
Usually you would use some solution for file uploads, like Carrierwave and in this specific case you would also have to use Globalize to manage Carrierwave translated fields, after you setup both gems in you gemfile and ran bundle install you would have to setup uploaders for each file upload rule you would like to enforce i.e.:
rails generate uploader Avatar
Then, initialize the uploader on your model file app/models/assets.rb on the string column/field like the code below:
class Asset < ApplicationRecord
extend CarrierwaveGlobalize
# Globalize translated attributes
translates :avatar
mount_translated_uploader :avatar, AvatarUploader
end
I have carrierwave's uploader working without applying any changes to uploaded images. Though when I comment out the version block in the generated uploader file I get an "undefined method `version' for main:Object" message.
version is a built in method, and based on what googled, and even a railscast video on it I should be able to just uncomment it and roll.
# Create different versions of your uploaded files:
version :thumb do
process :resize_to_limit => [313, 344]
end
What could I have going on in my codebase that would be causing an issue with carrierwave's version method?
Error implicitly says that your version method not in scope of carrierwave uploader.
Your uploader should look like this.
class Uploader < CarrierWave::Uploader::Base
version 'anything' do
....
end
end
But as per error your uploader code is some thing like this:
class Uploader < CarrierWave::Uploader::Base
...
end
version 'anything' do
....
end
As your version method is not present inside uploader. Ruby considering it for main object when try to execute.
Few more thing also you need to make sure present in your code. You must have rmagick gem in your gemfile. You have imagemagick installed on your development machine.
include CarrierWave::RMagick uncommented in your uploader.
I am using carrierwave to handle my uploads. I have specified the store_dir following way:
def store_dir
"uploads/#{Time.now.year}/#{Time.now.month}/#{Time.now.day}"
end
Uploading files work like a charm - each time I upload a file it ends up in directory where it should end; i.e. "today's directory".
When I try to download the file, carrierwave is constructing the download path dynamically based on store_dir options. So lets say a file which was uploaded on 1.12.2012 is available on the following path on fliesystem:
/uploads/2012/12/01/file.ext
will be retrieved by carrierwave as:
/uploads/2012/12/12/file.ext
Which obviously leads to "Cannot read file" error.
I came with 2 different possible solutions:
Create a separate filed where I will be storing the actual filepath to the file upon it's creation and then will use this value to retrieve file.
Overload retrieve_from_store! method (which is part of carrierwave gem) and make it construct path based on created_at field from the file record than rather from store_dir.
I am inclining to the second possibility since it feels not that dirty. Yet both feel "not-rails-way". Which one will be better to use and why? Or maybe carrierwave provides a way to solve this issue?
Totally guessing here but by looking at the docs I think something like this should work:
def store_dir
"uploads/#{model.created_at.year}/#{model.created_at.month}/#{model.created_at.day}"
end
I want to stub carrierwave to prevent it from fetch images on the web during my tests. How would I stub things to achieve this?
My crawler parses a remote web page, and saves one image url into the model. Carrierwave will fetch that image automatically during the save operation. It works well.
However I have a test about the parsing of pages, and every-time it will download the file, which slows down the testing.
UPDATE:
I mount the uploader as the following (in the pre-existing paperclip column)
mount_uploader :image, TopicImageUploader, :mount_on => :image_file_name
I tried to stub the following, but neither worked:
Topic.any_instance.stub(:store_image!)
Topic.any_instance.stub(:store_image_file_name!)
Topic.any_instance.stub(:store_image_remote_url!)
TopicImageUploader.any_instance.stub(:download!)
This is what I'm using in my spec_helper:
class CarrierWave::Mount::Mounter
def store!
end
end
This completely blocks all real file uploads (note that I'm using this with carrier wave 0.5.8, which is newest version at the time of writing, if you're using much older version, it might differ). If you want to control tests which stub uploads, you could use:
CarrierWave::Mount::Mounter.any_instance.stub(:store!)
I reduced my test-suite time from 25 seconds to just 2 seconds with a simple config in the CarrierWave initializer:
# config/initializers/carrier_wave.rb
CarrierWave.configure do |config|
config.enable_processing = false if Rails.env.test?
end
This config skips the image manipulation (resizing, cropping, ...) of ImageMagick, MiniMagick ect.
allow_any_instance_of(CarrierWave::Uploader::Base).to receive(:store!).and_return nil