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
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
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.
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.
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).
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.