Issues with Globalize and CarrierWave uploads in Rails 4.2 app - carrierwave

I have issues with translated files in my Rails 4.2 app.
Background
Here are the gem versions I'm using:
gem "rails", "4.2.1"
gem "carrierwave" # 0.10.0
gem "globalize" # 5.0.1
And my model:
class Download < ActiveRecord::Base
belongs_to :download_type
has_and_belongs_to_many :products
translates :title, :part_number, :file
mount_uploader :file, DownloadFileUploader
validates :title, presence: true
def to_param
"#{id}-#{title.parameterize}"
end
end
The Issues
In my view, I want to list a Download and all of the current translations for that download, but all I get is the current locale data for each translation. In the Rails console:
> I18n.locale
=> :en
> download = Download.find(481)
=> #<Download id: 481, title: "SmartSensor HD Quick-reference Guide (User)", part_number: "WX-500-0171", download_type_id: 3, created_at: "2015-01-16 22:49:13", updated_at: "2015-04-20 16:59:25", file: "smartsensor_hd_user_quick-reference_guide-20150116...", download_updated_at: nil>
> download.translations.count
=> 8
> download.translated_locales
=> [:de, :en, :es, :fr, :it, :pt, :ru, :"zh-CN"]
> download.file.class
=> DownloadFileUploader
> download.file.url
=> "/uploads/download/file/481/smartsensor_hd_user_quick-reference_guide-20150116154913-en.pdf"
> download.title
=> "SmartSensor HD Quick-reference Guide (User)"
> download.part_number
=> "WX-500-0171"
And when the locale changes:
> I18n.locale = :de
=> :de
> download.file.class
=> DownloadFileUploader
> download.file.url
=> "/uploads/download/file/481/smartsensor_hd_user_quick-reference_guide-20150116154913-en.pdf"
> download.title
=> "SmartSensor HD Kurzanleitung"
> download.part_number
=> "WX-502-0006"
If I try and access the translation directly:
> I18n.locale = :de
=> :de
> download.translation.file.class
=> String
If I change how the uploader is mounted in my model:
Translation.mount_uploader :file, DownloadFileUploader
Existing translations list correctly—including the file, but I can no longer upload files. What gets stored in the database is this:
/uploads/download/translation/file/401/%23%3CActionDispatch%3A%3AHttp%3A%3AUploadedFile%3A0x007f9c12e6fe00%3E
Notice that it inserts /translation into the path, which I can fix in the uploader, but the filename isn't actually a file.
If I move translates :title, :part_number, :file below mount_uploader :file, DownloadFileUploader in my model, Globalize overrides the mounted uploader and that column is returned as class String when accessing it.
The Cry for Help
Help! 😮

I wrote this simple gem https://github.com/dalpo/carrierwave_globalize. which it should allow to use Globalize and Carrierwave together.
You have to extend your model with the CarrierwaveGlobalize module and use the mount_translated_uploader class method to mount your carrierwave uploader instead of the mount_uploader mehtod.
Follow the instructions in the readme for more info.

Old question, but... do not use Globalize with CarrierWave on the same attribute, they both make overrides for the default behavior.
You can do this in your model:
class Download < ActiveRecord::Base
belongs_to :download_type
has_and_belongs_to_many :products
translates :title, :part_number
mount_uploader :file, DownloadFileUploader
validates :title, presence: true
def to_param
"#{id}-#{title.parameterize}"
end
end
And then override file storing for your uploader in system to use I18n.locale:
def store_dir
"uploads/#{I18n.locale}/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end

Related

Carrierwave error: version doesn't exist! in Rails

I´m using Carrierwave (2.0.2, 0.11.2) in Rails 5.2.3. and I´m pretty stuck with versions of uploaded images.
Imagemagick is latest version,gems Carrierwave,Rmagick and Minimagick installed.
Everything works as it should with two versions created by default and uncommented in uploaders/image_uploader.rb file:
just like this:
version :large do
process resize_to_fill: [500,500]
end
version :thumb from :large do
process resize_to_fit: [50, 50]
end
version :long do
process resize_to_fill: [500,200]
end
My model looks like this:
class Slide < ApplicationRecord
mount_uploader :image, ImageUploader
before_save :update_image_attributes
after_save :recreate_delayed_versions!
validates :image_title, presence: true
validates :display, presence: true
validates :order, presence: true
validates_presence_of :image
validates_integrity_of :image
validates_processing_of :image
def recreate_delayed_versions!
image.recreate_versions!(:thumb,:large,:long)
end
private
def update_image_attributes
if image.present? && image_changed?
self.image_content_type = image.file.content_type
self.image_file_size = image.file.size
end
end
end
Uploaded images are processed,scaled and saved in :original size,:large and :thumb version in correct folders...all good.
But if I try to create another version,or rename existing one,for example " version :long ",it doesn´t create it and in my views exception is caught as: "Version long doesn't exist!"
I did tried several different version names,amount of versions,name as symbol,in quotation marks,also reading the source code of Carrierwave/versions.rb,reading documentation,but still unable to find any reason for this behaviour.Only those two versions working well,not any other.Could You someone help me with it?
Thanks!
After rename the version or adding new version, you are required to recreate those versions by calling something like this:
User.find_each do |user|
user.avatar.recreate_versions!
end
Full documentation can be found here

no validates_attachment_file_name when upgrading to Paperclip 4.1 from 3.5

We have code that looks like run of the mill paper clip:
has_merchants_attached_file :pdf,
storage: :s3,
s3_credentials: Mbc::DataStore.s3_credentials,
s3_permissions: :private,
path: ":identifier_template.pdf",
bucket: Mbc::DataStore.forms_and_templates_bucket_name
validates_attachment_file_name :pdf, :matches => [/pdf\Z/]
Which generates an error:
undefined method `validates_attachment_file_name' for #<Class:0x007fba67d25fe0>
Interestingly enough, when we down grade back to 3.5, we encounter the same issue.
The controller that is generating this is:
def index
#fidelity_templates = FidelityTemplate.order("identifier asc").all
end
Additionally:
def has_merchants_attached_file(attribute, options={})
if Rails.env.test? || Rails.env.development?
has_attached_file attribute,
path: "paperclip_attachments/#{options[:path]}"
else
has_attached_file attribute, options
end
end
Any thoughts on what could be causing this?
You can read about the provided validators here:
https://github.com/thoughtbot/paperclip#validations
The included validators are:
AttachmentContentTypeValidator
AttachmentPresenceValidator
AttachmentSizeValidator
They can be used in either of these ways:
# New style:
validates_with AttachmentPresenceValidator, :attributes => :avatar
# Old style:
validates_attachment_presence :avatar
UPDATE ...
If you read further down the link I've given above you'll get to a section on Security Validations (Thanks Kirti Thorat):
https://github.com/thoughtbot/paperclip#security-validations
They give an example on how to validate the filename format:
# Validate filename
validates_attachment_file_name :avatar, :matches => [/png\Z/, /jpe?g\Z/]
From your code snippet it looks like your validation should work as-is.
However, I've never seen paperclip used with this syntax:
has_merchants_attached_file ...
Perhaps that's the source of your issues? You would usually use the following to attach files to your model:
has_attached_file :pdf ...

Can't upload image using Paperclip 4.0 Rails 3

I've installed ImageMagick and I've installed the gem Paperclip (version 4.0). I've added:
Paperclip.options[:command_path] = 'C:\Program Files\ImageMagick-6.8.8-Q16'
to the development.rb
My photo.rb Model has this:
has_attached_file :image
validates_attachment_content_type :image, :content_type => ['image/jpeg', 'image/png', 'image/jpg']
I can choose a file in photos/new.html.erb but once I click on 'Create photo' button, the page reloads with a Paperclip specific error message saying:
1 error prohibited this photo from being saved:
Image translation missing:
en.activerecord.errors.models.photo.attributes.image.spoofed_media_type
Can someone help please?
Thanks
Add this to an initializer to disable spoofing protection:
require 'paperclip/media_type_spoof_detector'
module Paperclip
class MediaTypeSpoofDetector
def spoofed?
false
end
end
end
That message is raised by a validation check for content spoofing.
For Paperclip v.4 this generates a bug https://github.com/thoughtbot/paperclip/issues/1429
While for Paperclip v.3, it seems it just throws a deprecation warning, https://github.com/thoughtbot/paperclip/issues/1423
So I'd wait for Paperclip team to solve this bug before using version 4. At the moment I'd rather keep using version 3.
gem "paperclip", "~> 3.5.3"
This works on Paperclip v3.5.1 (hopefully will still work in V4):
has_attached_file :attachment,
styles: lambda { |a| a.instance.is_image? ? { *** image_styles ***} : { *** video_styles ***},
processors: lambda { |a| a.is_video? ? [ :ffmpeg ] : [ :thumbnail ] }
def is_video?
attachment.instance.attachment_content_type =~ %r(video)
end
def is_image?
attachment.instance.attachment_content_type =~ %r(image)
end

Cloudinary URLs break with Mongoid 3?

I've using the Cloudinary gem, which up until now has worked fine as an embedded Photo model in Mongoid:
class PhotoUploader < CarrierWave::Uploader::Base
include Cloudinary::CarrierWave
def public_id
return model.id
end
end
class Photo
include Mongoid::Document
include Mongoid::Timestamps
embedded_in :place#, :inverse_of => :photos, :autosave => true
mount_uploader :image, PhotoUploader
#...
end
However, after upgrading to Mongoid 3, getting the image URL no longer works. Consider this Photo model:
1.9.3p194 :019 > p
=> #<Photo _id: 507bc3c82a450b14bd00e00a, _type: nil, created_at: 2012-10-15 08:05:28 UTC, updated_at: 2012-10-15 08:05:28 UTC, image_filename: nil, caption: nil, original_url: "http://www.reactionny.com//images/assets/101755_316529.JPG", image: "v1350288333/507bc3c82a450b14bd00e00a.jpg">
1.9.3p194 :020 > p.image
=> /assets/fallback/default.png
1.9.3p194 :021 > p.image_url
=> "/assets/fallback/default.png"
1.9.3p194 :022 > p['image']
=> "v1350288333/507bc3c82a450b14bd00e00a.jpg"
Why is it no longer returning the fully-qualified Cloudinary URL, in the form http://res.cloudinary.com/XXXXXX/image/upload/v1350288842/507bc5ca2a450b14bd00e896.jpg?
It seems that carrierwave-mongoid changed the name of the field in which the image is saved from yyy to yyy_filename.
In your model inspection printing you can see that image_filename is nil.
The integration with the Cloudinary GEM and CarrierWave seems to be working fine, but you need to migrate your model.
The relevant field used to be called 'image' and it's now called 'image_filename'. You should probably update your model to use the new field name and copy all values.
Another possible solution would be to specifically set the attribute name using mount_on:
mount_uploader :image, PhotoUploader, mount_on: :image

multiple paperclip attachements with watermark processor

I'm having a ton of trouble with uploading multiple attachments with paperclip and processing them with a watermark.
I have 2 models, Ad and Photo.
The Ad has_many :photos and the Photo belongs_to :ad.
To be more exact in /models/ad.rb I have:
class Ad < ActiveRecord::Base
has_many :photos, :dependent => :destroy
accepts_nested_attributes_for :photos, :allow_destroy => true
end
and my photo.rb file looks like this:
class Photo < ActiveRecord::Base
belongs_to :ad
has_attached_file :data,
:styles => {
:thumb => "100x100#",
:first => {
:processors => [:watermark],
:geometry => '300x250#',
:watermark_path => ':rails_root/public/images/watermark.png',
:position => 'SouthEast' },
:large => {
:processors => [:watermark],
:geometry => '640x480#',
:watermark_path => ':rails_root/public/images/watermark.png',
:position => 'SouthEast' }
}
end
In my view I use this to add the file fields
<% f.fields_for :photos do |p| %>
<%= p.label :data, 'Poza:' %> <%= p.file_field :data %>
<% end %>
In my controller, in the edit action i use 4.times {#ad.photos.build} to generate the file fields.
It all works fine and dandy if I don't use the watermark processor, if I use a normal has_attached_file declaration, like this:
has_attached_file :data,
:styles => {
:thumb => "100x100#",
:first => '300x250#',
:large => '640x480#'
}
But when I use the watermark processor I always get this error:
NoMethodError in PublicController#update_ad
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]
..............................
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/nested_attributes.rb:350:in `assign_nested_attributes_for_collection_association'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/nested_attributes.rb:345:in `each'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/nested_attributes.rb:345:in `assign_nested_attributes_for_collection_association'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/nested_attributes.rb:243:in `photos_attributes='
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2746:in `send'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2746:in `attributes='
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2742:in `each'
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2742:in `attributes='
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2628:in `update_attributes'
/home/alexg/Sites/vandmasina/app/controllers/public_controller.rb:217
/home/alexg/Sites/vandmasina/app/controllers/public_controller.rb:216:in `update_ad'
The parameters are ok, as far as I can say
Parameters:
{"commit"=>"Salveaza modificarile",
"ad"=>{"price"=>"6000",
"oras"=>"9",
"photos_attributes"=>{"0"=>{"data"=>#<File:/tmp/RackMultipart20100928-5130-b42noe-0>},
"1"=>{"data"=>#<File:/tmp/RackMultipart20100928-5130-r0ukcr-0>},
"2"=>{"data"=>#<File:/tmp/RackMultipart20100928-5130-mb23ei-0>},
"3"=>{"data"=>#<File:/tmp/RackMultipart20100928-5130-1bpkm3b-0>}},
The Watermark processor /lib/paperclip_processors/watermark.rb looks like this:
module Paperclip
class Watermark < Processor
class InstanceNotGiven < ArgumentError;
end
def initialize(file, options = {},attachment = nil)
super
#file = file
#current_format = File.extname(#file.path)
#basename = File.basename(#file.path, #current_format)
#watermark = ':rails_root/public/images/watermark.png'
#current_geometry = Geometry.from_file file # This is pretty slow
#watermark_geometry = watermark_dimensions
end
def watermark_dimensions
return #watermark_dimensions if #watermark_dimensions
#watermark_dimensions = Geometry.from_file #watermark
end
def make
dst = Tempfile.new([#basename, #format].compact.join("."))
watermark = " \\( #{#watermark} -extract #{#current_geometry.width.to_i}x#{#current_geometry.height.to_i}+#{#watermark_geometry.height.to_i /
2}+#{#watermark_geometry.width.to_i / 2} \\) "
command = "-gravity center " + watermark + File.expand_path(#file.path) + " " +File.expand_path(dst.path)
begin
success = Paperclip.run("composite", command.gsub(/\s+/, " "))
rescue PaperclipCommandLineError
raise PaperclipError, "There was an error processing the watermark for #{#basename}" if #whiny_thumbnails
end
dst
end
end
end
I have tried the processor in a normal app, without multiple attachments and it works perfect. It doesn't work with nested_attributes as far as I can tell.
The app is rails 2.3.5 with ruby 1.8.7 and paperclip 2.3.11
If you can provide any help it would be appreciated a lot, since I've been trying to figure this out for 2 days now :)
If you use rails 3 and paperclip > 2.3.3, try https://gist.github.com/843418 source.
Oh, man, that was a tough one!
You have few errors in your code and none is related to nested models. My explanation is for Rails 3 & Paperclip 2.3.3
a) the :rails_root thing doesn't work. This interpolation is used only in url/path and not on custom options. So you should replace it with Rails.root.join("public/images...")
b) you simply ignore the :watermark_path option and you use only hardcoded path (in initialization method). So it doesn't matter what you have in your :styles as it always go for .../images/watermark.png. The :rails_root thingy there again so it cannot work.
c) when you pass a parameter to Paperclip.run("composite", "foo bar there") it actually executes this command:
composite 'foo bar there'
can you see the single quotes? Because of that the composite command see your parameters as one huge parameter and doesn't understand it at all. If you pass it as an array, then every item is enclosed in the quotes, not the array as a whole.
So here is the improved version of watermark processor:
module Paperclip
class Watermark < Processor
class InstanceNotGiven < ArgumentError;
end
def initialize(file, options = {},attachment = nil)
super
#file = file
#current_format = File.extname(#file.path)
#basename = File.basename(#file.path, #current_format)
# PAWIEN: use default value only if option is not specified
#watermark = options[:watermark_path] || Rails.root.join('public/images/watermark.png')
#current_geometry = Geometry.from_file file # This is pretty slow
#watermark_geometry = watermark_dimensions
end
def watermark_dimensions
return #watermark_dimensions if #watermark_dimensions
#watermark_dimensions = Geometry.from_file #watermark
end
def make
dst = Tempfile.new([#basename, #format].compact.join("."))
dst.binmode
begin
# PAWIEN: change original "stringy" approach to arrayish approach
# inspired by the thumbnail processor
options = [
"-gravity",
"center",
"#{#watermark}",
"-extract",
"#{#current_geometry.width.to_i}x#{#current_geometry.height.to_i}+#{#watermark_geometry.height.to_i / 2}+#{#watermark_geometry.width.to_i / 2}",
File.expand_path(#file.path),
File.expand_path(dst.path)
].flatten.compact.join(" ").strip.squeeze(" ")
success = Paperclip.run("composite", options)
rescue PaperclipCommandLineError
raise PaperclipError, "There was an error processing the watermark for #{#basename}" if #whiny_thumbnails
end
dst
end
end
end
Hope that helped you!
UPDATE: You need to use latest paperclip gem from github
gem 'paperclip', '>= 2.3.3', :git => "http://github.com/thoughtbot/paperclip.git"
In this version the formats of #run were changed once again so I've updated the code. It really should work as I've created test application and it's doing what supposed.
UPDATE 2: Repo with working example:
git://repo.or.cz/paperclip-mass-example.git
Just from a quick glance it looks like watermark_path should be "#{Rails.root}/..." though it looks like you have a lot going on here.
Also, I don't see your form as in form_for. Make sure you have {:multipart => true}

Resources