Having troubles writing RSpec tests for my implementation of "auto_orient" on my CarrierWave uploader. Im also not finding much love on the matter online.
I understand that the manipulate method would be specced by the gem, but Im just wanting to validate that my ImageUploader is implementing it correctly with RSpec.
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
...
version :tile do
process :auto_orient
end
# Fix images being uploaded the wrong orientation
def auto_orient
manipulate! do |img|
img = img.auto_orient
end
end
let(:uploader) { ImageUploader.new(profile, :avatar) }
before do
ImageUploader.enable_processing = true
File.open(File.join(Rails.root, '/spec/support/images/logo.png')) { |f| uploader.store!(f) }
end
after do
ImageUploader.enable_processing = false
uploader.remove!
end
xit 'runs auto_orient on the image' do
# ???
end
Thanks
I'm not 100% sure how to do this in MiniMagick exactly, but here's how I approached the problem using RMagick if that helps. Should be a similar approach I would think.
uploader.cache_stored_file!
# For minimagick, you would probably use MiniMagick::Image::read
mg = ::Magick::Image::read(uploader.file.file).first
# Not sure if minimagick has an "orient" attribute, might try reading the data using something from here instead: https://github.com/probablycorey/mini_magick/blob/master/lib/mini_magick.rb#L204
expect(mg.orientation.to_i).to eq(1)
Related
I've introduced a new version on my Carrierwave Uploader. When I create a new Event it creates both versions correctly. But when I update it, only the file I attached gets uploaded, but versions do not get recreated.
I am using CarrierWave 1.2.2, and looking at the changelog, it doesn't seem to have been a bug that got fixed in the newer versions
class CoverUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
if Rails.env.development? || Rails.env.test?
storage :file
elsif Rails.env.production?
storage :fog
end
# 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
if ENV['HEROKU_APP_NAME'].to_s.include?('-pr-')
"review_apps/#{model.class.to_s.underscore}/#{model.id}"
else
"#{Rails.env}/#{model.class.to_s.underscore}/#{model.id}"
end
end
# Provide a default URL as a default if there hasn't been a file uploaded:
def default_url(*args)
ActionController::Base.helpers.asset_path('test.jpg')
end
# Create different versions of your uploaded files:
version :optimised do
process convert: 'webp'
process :set_content_type_to_webp
def full_filename(_for_file = model.cover.file)
"cover_#{model.id}.webp"
end
def exists?
file&.exists?
end
end
def extension_blacklist
%w(webp)
end
private
# Required to actually force Amazon S3 to treat it like an image
def set_content_type_to_webp
file.instance_variable_set(:#content_type, 'image/webp')
end
end
#ogelacinyc was partly correct when he found the bug in full_filename. I went back to test normal functionality with creating another version, with a simple dimension change. I could then see that update would recreate the versions by itself, just like I expected.
That made me think that maybe there is something wrong with my version :optimised block. So after commenting one by one, I found that full_filename was the culprit. It could have been model.cover.file failing silently, but I think it was model.id, as can be seen in the description for filename method in Carrierwave
So instead, I grab the filename directly, extract extension and substitute it with webp:
def full_filename(for_file = model.file_name.file)
extension = File.extname(for_file)
"cover_#{for_file.sub(extension, '.webp')}"
end
Which works without problems!
You need to add an after_save callback to Event and then call recreate_versions! on your mounted uploader.
Assuming you have an Event model with the following, this would solve your problem.
class Event < ApplicationRecord
mount_uploader :cover_image, CoverUploader
after_save :recreate_versions!
delegate :recreate_versions!, to: :cover_image, allow_nil: true
end
See CarrierWave's README also.
I am using carrierwave with minimagick to upload an image and crop it to a square. However I get the following error:
undefined method 'manipulate!' for #<Class:0x692db10>
it seems to make no sense, as i have included the correct class, and that part works fine. Heres my current uploader class.
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
##sizes = {
"2000" => 2048,
"1500" => 1500,
"1000" => 1024,
"500" => 512,
"250" => 256,
"100" => 128
}
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :square do
manipulate! do |img|
size = img.dimensions.min
end
process resize_to_fill: [size, size]
end
end
to be clear, we are talking about the :square version. Does anyone have any idea what could be wrong?
It seems manipulate! belongs to RMagick adapter, for MiniMagick you should use something like mogrify.
Indeed, there's such method, but you're trying to use it in a class scope, while it's an instance method. There's a bunch of useful class methods you can use already.
If you still need manipulate!, make something like this:
process :radial_blur => 10
def radial_blur(amount)
manipulate! do |img|
img.radial_blur(amount)
img = yield(img) if block_given?
img
end
end
I am trying to add additional fields to the CarrierWave Uploader so that they are stored as part of the Uploader itself and together with the CarrierWave fields, such as #file, #model, #storage etc.
The fields are also version-specific, which is why I'd prefer to be able to access them via <my_model>.<my_uploader>.attribute and<my_model>.<my_uploader>.versions[:<the_version>] instead of additional columns in the model.
I did try the carrierwave-meta gem, but ran into an error with it ( NoMethodError: undefined method \'original_filename' for #<CarrierWave::Storage::Fog::File:0xab4134c> )
that seems to not have been fixed yet.
Any ideas or suggestions on how to best accomplish this?
I'm not 100% clear what you are trying to do.
when I use carrierwave gem, I do create a path that holds some of that information. In my applaications I normally have a file app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
def store_dir
# "uploads/image/file/187/"
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
...
end
from this I always know the model, what type of file, and the id.
All other info about this model I normally save in the database.
I hope this helps and sets you in the right direction
your error is connected with fog
In my Picture Uploader I can set an attribute reader and writer
class PictureUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
def field
#field
end
def field=(field)
#field = field
end
# attr_accessor :field # for an even shorter way
end
The I open the rails console to test the model:
picture = PictureUploader.new
=> #<PictureUploader:0x0055804db336e8 #model=nil, #mounted_as=nil>
picture.field=('your text')
=> "your text"
picture.field
"your text"
About the versioning and error you are having 'NoMethodError: undefined method \'original_filename' for #<CarrierWave::Storage::Fog::File:0xab4134c>' I agree with MZaragoza
CarrierWave::Storage::Fog::File.new takes three parameters
def store!(file)
f = CarrierWave::Storage::Fog::File.new(uploader, self, uploader.store_path)
f.store(file)
f
end
uploader, self and uploader.store_path so to help us solve this problem you should include your CarrierwaveUploader model code and the output of uploader.store_path
Thanks a lot
I have an Event model that has many photographs. I have an image uploader mounted to the Photographs attribute, and regular uploads and everything is working fine.
However, when I try and duplicate an event, recreating a new photograph object for the new event, the new image is darker than the original, and if I duplicate the duplicate event, it gets darker still.
I have played around with it, but have no solution.
My Uploader code:
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
include CarrierWave::Processing::RMagick
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def cache_dir
"#{Rails.root}/tmp/carrierwave"
end
process :colorspace => :rgb
# Remove EXIF data
process :strip
# Create different versions of your uploaded files:
version :thumb do
process :resize_to_limit => [640, 640]
end
version :preview_thumb do
process :resize_to_limit => [600, 600]
end
version :wine_thumb do
process :resize_to_limit => [160, 440]
end
version :logo_thumb do
process :resize_to_limit => [90, 90]
end
end
And my duplcation code (in Active Admin):
member_action :create_duplicate_event, method: :post do
old_event = Event.find(params[:id])
photograph_urls = old_event.photographs.map(&:image_url)
attributes = old_event.attributes.except("photographs", "id")
new_photos = []
photograph_urls.each do |photo|
new_photo = Photograph.new({
remote_image_url: photo
})
if new_photo.save
new_photos << new_photo
end
end
#event = Event.new(attributes)
#event.photograph_ids = new_photos.map(&:id)
render "/admin/events/_events_form/"
end
The :rgb tag was an attempt to fix. But no luck.
Ruby 2.1 and Rails 4.0
Ok, after a lot of playing around and searching I managed to fix this problem.
First, you need to download the .icc color profiles, which can be found here. It says for windows but they seemed to work for me on my Mac.
Once you have put the .icc files into a /lib/color_profiles directory, add the following code to your uploader:
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
process :convert_image_from_cmyk_to_rgb
#versions, and any other uploader code go here
def convert_image_from_cmyk_to_rgb
manipulate! do |image|
if image.colorspace == Magick::CMYKColorspace
image.strip!
image.add_profile("#{Rails.root}/lib/USWebCoatedSWOP.icc")
image.colorspace == Magick::SRGBColorspace
image.add_profile("#{Rails.root}/lib/sRGB.icc")
end
image
end
end
end
This converts CMYK images to RGB, and keeps the profiles keeping nice, while keeping RGB images as they were, and not ruining them.
I hope this helps someone in the future, and saves them the hours I spent working this out.
I am using Rails 4, and trying to upload an image and then store it after processing it.
I am using just one view, where I want the user to upload the image, I process the image, store it in db, and then reload the page with the new processed image.
My model (user.rb)
class User < ActiveRecord::Base
mount_uploader :image, ImageUploader
end
Uploader (image_uploader.rb)
# encoding: utf-8
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
process :changeImage
def changeImage
manipulate! do |source|
source = source.sepiatone
end
end
Controller (app_main_controller.rb)
require 'Rmagick'
class AppMainController < ApplicationController
def index
# page reload handling when the file uploads
if(params.has_key?("file-input"))
#u= User.new
#u.image = params["file-input"]
if(#u.save)
render js: "alert('SAVED')"
else
render js: "alert('Error while saving image! Try Again!')"
end
# initial page load
else
end
end
end
I access the image-uploader in my view (i.e. index) with image_tag #u.image_url
I keep on getting "stack level too deep" everytime I add any kind of processing in image_uploader.rb. If no processing is added, the image gets uploaded fine.
Any ideas, anyone?
I am experiencing the same problem. It looks like an issue with the rmagick gem.
EDIT:
The problem is with case. Try this instead:
gem 'rmagick', :require => 'RMagick'
See also this stackoverflow answer and this issue or this issue on github.
I switched to mini_magick to fix it. (Not ideal, but it's working for me now.)
Uploader class (comment out RMagick):
include CarrierWave::MiniMagick
Gemfile:
gem 'mini_magick'