Paperclip how to change basename (filename)? - ruby-on-rails

I am trying to change the basename (filename) of photos:
In my model I have:
attr_accessor :image_url, :basename
has_attached_file :image,
:styles => { :original => ["300x250>", :png], :small => ["165x138>", :png] },
:url => "/images/lille/:style/:id/:basename.:extension",
:path => ":rails_root/public/images/lille/:style/:id/:basename.:extension"
before_save :basename
private
def basename
self.basename = "HALLLO"
end
But the filename is not changed at all.

If you are assigning the file directly you can do this:
photo.image = the_file
photo.image.instance_write(:file_name, "the_desired_filename.png")
photo.save

Im doing this to strip whitespaces:
before_post_process :transliterate_file_name
private
def transliterate_file_name
self.instance_variable_get(:#_paperclip_attachments).keys.each do |attachment|
attachment_file_name = (attachment.to_s + '_file_name').to_sym
if self.send(attachment_file_name)
self.send(attachment).instance_write(:file_name, self.send(attachment_file_name).gsub(/ /,'_'))
end
end
end
I hope this will help you.
edit:
In your example:
def basename
self.image_file_name = "foobar"
end
Should do the job. (but might rename the method ;) )

Paperclip now allows you to pass in a FilenameCleaner object when setting up has_attached_file.
Your FilenameCleaner object must respond to call with filename as the only parameter. The default FilenameCleaner removes invalid characters if restricted_characters option is supplied when setting up has_attached_file.
So it'll look something like:
has_attached_file :image,
filename_cleaner: MyRandomFilenameCleaner.new
styles: { thumbnail: '100x100' }
And MyRandomFilenameCleaner will be:
class MyRandomFilenameCleaner
def call(filename)
extension = File.extname(filename).downcase
"#{Digest::SHA1.hexdigest(filename + Time.current.to_s).slice(0..10)}#{extension}"
end
end
You could get away with passing in a class that has a self.call method rather than an object but this conforms to Paperclip's documentation in Attachment.rb.

I wanted to avoid having to add a before_create callback to every model with an attachment. I had a look at the source and at the time of this writing it looked sth like:
module Paperclip
class Attachment
...
def assign_file_information
instance_write(:file_name, cleanup_filename(#file.original_filename))
instance_write(:content_type, #file.content_type.to_s.strip)
instance_write(:file_size, #file.size)
end
So you could just patch cleanup_filename.
config/initializers/paperclip.rb
module Paperclip
class Attachment
def cleanup_filename(filename)
"HALLLO"
end
end
end

Related

Rails paperclip default image only under certain conditions

I've got a Lead model which is splited by lead_status param on products and offers. Only leads with product status should contain images and offers should not. I've migrated attached product_image table to schema and tried to set a default image only for products. Like this:
class Lead < ApplicationRecord
has_attached_file :product_image, styles: { small: "150x150>", default: "350x350"}
validates_attachment_content_type :product_image, content_type: /\Aimage\/.*\z/
before_save :product_image_default_url
def product_image_default_url
if self.lead_status == "product" && self.product_image.url.nil?
self.product_image.url = "/images/:style/default_user_avatar.png"
end
end
Every time when I save a new lead without uploaded image I get "/product_images/original/missing.png" as a default url. No matter which status it has.
Model doesn't recognize new leads by it's status
How can I change that? Force my Lead model to save a default image url according to a "product" status and ignore all those with "offer" status?
My rails version is 5.2.1 and paperclip 6.0.0
Try with following,
has_attached_file
:product_image,
styles: { small: "150x150>", default: "350x350"},
default_url: ":style/default_user_avatar.png"
# app/assets/images/medium/default_user_avatar.png
# app/assets/images/thumbs/default_user_avatar.png
Existing method is,
def default_url
if #attachment_options[:default_url].respond_to?(:call)
#attachment_options[:default_url].call(#attachment)
elsif #attachment_options[:default_url].is_a?(Symbol)
#attachment.instance.send(#attachment_options[:default_url])
else
#attachment_options[:default_url]
end
end
In initializer, Provide monkey patch for following,
require 'uri'
require 'active_support/core_ext/module/delegation'
module Paperclip
class UrlGenerator
def default_url
if #attachment.instance.lead_status == 'product'
default_url = attachment_options[:default_url]
else
default_url = # provide another missing default_url
end
if default_url.respond_to?(:call)
default_url.call(#attachment)
elsif default_url.is_a?(Symbol)
#attachment.instance.send(default_url)
else
default_url
end
end
end
end
Update as per cases

Displaying an Image from Rails Seeds.rb [duplicate]

Please suggest me a way to save an image from an URL by Paperclip.
In Paperclip 3.1.4 it's become even simpler.
def picture_from_url(url)
self.picture = URI.parse(url)
end
This is slightly better than open(url). Because with open(url) you're going to get "stringio.txt" as the filename. With the above you're going to get a proper name of the file based on the URL. i.e.
self.picture = URI.parse("http://something.com/blah/avatar.png")
self.picture_file_name # => "avatar.png"
self.picture_content_type # => "image/png"
Here is a simple way:
require "open-uri"
class User < ActiveRecord::Base
has_attached_file :picture
def picture_from_url(url)
self.picture = open(url)
end
end
Then simply :
user.picture_from_url "http://www.google.com/images/logos/ps_logo2.png"
It didn't work for me until I used "open" for parsed URI.
once I added "open" it worked!
def picture_from_url(url)
self.picture = URI.parse(url).open
end
My paperclip version is 4.2.1
Before open it wouldn't detect the content type right, because it wasn't a file. It would say image_content_type: "binary/octet-stream", and even if I override it with the right content type it wouldn't work.
First download the image with the curb gem to a TempFile and then simply assign the tempfile object and save your model.
Into official documentation is reported here https://github.com/thoughtbot/paperclip/wiki/Attachment-downloaded-from-a-URL
Anyway it seems not updated, because in last version of paperclip something has changed and this line of code is no more valid:
user.picture = URI.parse(url)
It raise an error, in particular this error is raised:
Paperclip::AdapterRegistry::NoHandlerError: No handler found for #<URI:: ...
The new correct syntax is this one:
url = "https://www.example.com/photo.jpeg"
user.picture = Paperclip.io_adapters.for(URI.parse(url).to_s, { hash_digest: Digest::MD5 })
Also we need to add these lines into config/initializers/paperclip.rb file:
Paperclip::DataUriAdapter.register
Paperclip::HttpUrlProxyAdapter.register
Tested this with paperclip version 5.3.0 and it works.
It may helpful to you. Here is the code using paperclip and image present in remote URL .
require 'rubygems'
require 'open-uri'
require 'paperclip'
model.update_attribute(:photo,open(website_vehicle.image_url))
In model
class Model < ActiveRecord::Base
has_attached_file :photo, :styles => { :small => "150x150>", :thumb => "75x75>" }
end
As those are old Answer's here's a newer one:
Add Image Remote URL to your desired Controller in the Database
$ rails generate migration AddImageRemoteUrlToYour_Controller image_remote_url:string
$ rake db:migrate
Edit your Model
attr_accessible :description, :image, :image_remote_url
.
.
.
def image_remote_url=(url_value)
self.image = URI.parse(url_value) unless url_value.blank?
super
end
*In Rails4 you have to add the attr_accessible in the Controller.
Update your form, if you allow other to upload an Image from a URL
<%= f.input :image_remote_url, label: "Enter a URL" %>
This is a hardcore method:
original_url = url.gsub(/\?.*$/, '')
filename = original_url.gsub(/^.*\//, '')
extension = File.extname(filename)
temp_images = Magick::Image.from_blob open(url).read
temp_images[0].write(url = "/tmp/#{Uuid.uuid}#{extension}")
self.file = File.open(url)
where Uuid.uuid just makes some random ID.

Paperclip :default_url

I have a lot of files with has_attached_file method from paperclip but without :default_url; now I want to use the same image for all of them but I don't want to go from file to file and add this :default_url line for each file. There are some solution to set this in one place and will work for all the has_attached_file method calls?
I tried to do it in this way, but seems like it does not have any effect
module Paperclip
module ClassMethods
def has_attached_file(name, options = {})
options[:default_url] => Rails.root + "/missing.png"
HasAttachedFile.define_on(self, name, options)
end
end
end
You are about to make it work – just change options[:default_url] => Rails.root + "/missing.png" to options[:default_url] = Rails.root + "/missing.png" (= instead of =>).
However, I suggest a better solution:
module Paperclip
module ClassMethods
def has_attached_file_with_preconfigured_default_url(name, options = {})
options.reverse_merge! default_url: Rails.root + "/missing.png"
has_attached_file_without_preconfigured_default_url(name, options)
end
alias_method_chain :has_attached_file, :preconfigured_default_url
end
end
# Now you could use both new has_attached_file and old has_attached_file_without_preconfigured_default_url.
And place this code into initializer.

Store uploaded files carrierwave RoR

i am trying to upload a file with carrierwave in my rails app and currently this is my code:
Controller:
def fileSave
#code.store!(code)
end
View:
= form_for #code = Code.new(params[:code]), :as => :code, :html => {:multipart => true} do |f|
div class="browse"
span
= f.file_field :code
= f.submit 'Upload'
Uploader:
# encoding: utf-8
class CodeUploader < CarrierWave::Uploader::Base
def pre_limit file
#require 'debugger'; debugger
if file && file.size > 100.megabytes
raise Exception.new('too large')
end
true
end
storage :file
def store_dir
"public/uploads"
end
def extension_white_list
%w(txt js ttf html)
end
def filename
"file.txt" if original_filename
end
end
Model:
require 'carrierwave/orm/activerecord'
class Code < ActiveRecord::Base
attr_accessor :code
mount_uploader :code, CodeUploader
end
And my problem is i can not store the uploaded file. x[ I am sure this is like 3 lines of code but i can not figure it out. Also the file to be uploaded is expected to be txt (probably figured that out looking the extension list).
Thanks to all readers and answerers. :}
P.S. I was wondering if i could create some kind of imaginary file, a file which is not really created. The is idea is if a take a text from a textarea and create a file (the imaginary one), store the text inside and then eventually save the whole file (maybe use carrierwave as and manually store it).

Save image from URL by paperclip

Please suggest me a way to save an image from an URL by Paperclip.
In Paperclip 3.1.4 it's become even simpler.
def picture_from_url(url)
self.picture = URI.parse(url)
end
This is slightly better than open(url). Because with open(url) you're going to get "stringio.txt" as the filename. With the above you're going to get a proper name of the file based on the URL. i.e.
self.picture = URI.parse("http://something.com/blah/avatar.png")
self.picture_file_name # => "avatar.png"
self.picture_content_type # => "image/png"
Here is a simple way:
require "open-uri"
class User < ActiveRecord::Base
has_attached_file :picture
def picture_from_url(url)
self.picture = open(url)
end
end
Then simply :
user.picture_from_url "http://www.google.com/images/logos/ps_logo2.png"
It didn't work for me until I used "open" for parsed URI.
once I added "open" it worked!
def picture_from_url(url)
self.picture = URI.parse(url).open
end
My paperclip version is 4.2.1
Before open it wouldn't detect the content type right, because it wasn't a file. It would say image_content_type: "binary/octet-stream", and even if I override it with the right content type it wouldn't work.
First download the image with the curb gem to a TempFile and then simply assign the tempfile object and save your model.
Into official documentation is reported here https://github.com/thoughtbot/paperclip/wiki/Attachment-downloaded-from-a-URL
Anyway it seems not updated, because in last version of paperclip something has changed and this line of code is no more valid:
user.picture = URI.parse(url)
It raise an error, in particular this error is raised:
Paperclip::AdapterRegistry::NoHandlerError: No handler found for #<URI:: ...
The new correct syntax is this one:
url = "https://www.example.com/photo.jpeg"
user.picture = Paperclip.io_adapters.for(URI.parse(url).to_s, { hash_digest: Digest::MD5 })
Also we need to add these lines into config/initializers/paperclip.rb file:
Paperclip::DataUriAdapter.register
Paperclip::HttpUrlProxyAdapter.register
Tested this with paperclip version 5.3.0 and it works.
It may helpful to you. Here is the code using paperclip and image present in remote URL .
require 'rubygems'
require 'open-uri'
require 'paperclip'
model.update_attribute(:photo,open(website_vehicle.image_url))
In model
class Model < ActiveRecord::Base
has_attached_file :photo, :styles => { :small => "150x150>", :thumb => "75x75>" }
end
As those are old Answer's here's a newer one:
Add Image Remote URL to your desired Controller in the Database
$ rails generate migration AddImageRemoteUrlToYour_Controller image_remote_url:string
$ rake db:migrate
Edit your Model
attr_accessible :description, :image, :image_remote_url
.
.
.
def image_remote_url=(url_value)
self.image = URI.parse(url_value) unless url_value.blank?
super
end
*In Rails4 you have to add the attr_accessible in the Controller.
Update your form, if you allow other to upload an Image from a URL
<%= f.input :image_remote_url, label: "Enter a URL" %>
This is a hardcore method:
original_url = url.gsub(/\?.*$/, '')
filename = original_url.gsub(/^.*\//, '')
extension = File.extname(filename)
temp_images = Magick::Image.from_blob open(url).read
temp_images[0].write(url = "/tmp/#{Uuid.uuid}#{extension}")
self.file = File.open(url)
where Uuid.uuid just makes some random ID.

Resources