I am using carrierwave to upload images in my rails project. This is my uploader class.
class ProfilePictureUploader < CarrierWave::Uploader::Base
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
I am not using mount_uploader :avatar , ProfilePictureUploader in my model. Instead I use this in my model
uploader = ProfilePictureUploader.new
uploader.store!(file)
self.image = uploader.url
self.save
But this is giving me an error saying
NoMethodError (undefined method `id' for nil:NilClass)
Understandably the model instance is not available in ProfilePictureUploader. So store_dir method can't access model.id. How can I get a similar directory structure with this flow.
This is not a duplicate of this problem . For me , the model attribute of uploader is not available.
I think you should properly initialize your uploader with your model instance:
mounted_as = "profile-or-something-else"
uploader = ProfilePictureUploader.new(self, mounted_as)
uploader.store!(file)
self.image = uploader.url
self.save
Related
I got a following error when using active storage in rails 6.
NoMethodError: undefined method `rails_blob_path' for #<Module:0x00007fb91cb006a8>
My env
rails 6.0.0(api mode)
ruby '2.6.3'
I already installed active storage and execute migrate
config/environments/development.rb
config.active_storage.service = :local
Model
class Contract < ApplicationRecord
...
has_one_attached :original_file
end
Serializer
class ContractSerializer < ActiveModel::Serializer
include Rails.application.routes.url_helpers
attributes :id, :original_file
def original_file
Rails.application.routes.default_url_options[:host] = 'localhost:3000'
Rails.application.routes.url_helpers.rails_blob_path(object.original_file, only_path: true) if object.original_file.attached?
end
end
If you have any tips, Please let me know if you know anything about this. Thank you.
The include statement and the full path to rails_blob_path method seem to be OK.
It looks like there is a naming issue.
You have created attribute and method with the same name.
Try to change one of them.
You should do like this :
Rails.application.routes.url_helpers.rails_representation_url(object.original_file(resize: "300x300").processed, only_path: true)
Source : https://stackoverflow.com/a/53547638/2679301
An Image model has a 1:1 association with an Organization model. In the organizations controller, the create method calls on an Image model method called upload_file.
def create
#organization = Organization.new(new_params)
if #organization.save
Image.upload_file(#organization.id)
end
end
The upload_file method uses a carrierwave uploader to store a standard file in an Amazon S3 bucket. To this end, the Image model includes mount_uploader :file_name, ImageUploader.
My question is how to create an Image instance for the uploaded file? The path to the stored file should be stored in the column file_name in the Image model. And the organization associated with the image should be stored in the column organization_id in the Image model. How can I do this? More specifically, what code should I add for this to the model method below? (also see the comments in the method below.
def self.upload_file(organization_id)
file = 'app/assets/emptyfile.xml'
uploader = ImageUploader.new
uploader.store!(file)
# Am I correct to assume that the previous line uploads the file using the uploader, but does not yet create an Image record?
# If so, then perhaps the next line should be as follows?:
# Image.create!(organization_id: organization_id, filename: file.public_url)
# I made up "file.public_url". What would be the correct code to include the path that the uploader stored the image at (in my case an Amazon S3 bucket)?
end
Currently in rails console I get the following error:
>> uploader = ImageUploader.new
=> #<ImageUploader:0x00000005d24f88 #model=nil, #mounted_as=nil, #fog_directory=nil>
>> file = 'app/assets/emptyfile.xml'
=> "app/assets/emptyfile.xml"
>> uploader.store!(file)
CarrierWave::FormNotMultipart: CarrierWave::FormNotMultipart
from /usr/local/rvm/gems/ruby-2.2.1/gems/carrierwave-0.10.0/lib/carrierwave/uploader/cache.rb:120:in `cache!'
etc.
You don't have to call the uploader yourself. Carrierwave comes with a mechanism to do the uploading and storing in AR models for you:
class Organization < ActiveRecord::Base
mount_uploader :image, ImageUploader
end
Then you can do
u = Organization.new
u.image = params[:file] # Assign a file like this, or
# like this
File.open('somewhere') do |f|
u.image = f
end
u.save!
u.image.url # => '/url/to/file.png'
u.image.current_path # => 'path/to/file.png'
u.image # => 'file.png'
Please visit the carrierwave README for more extensive examples.
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'm trying to recreate the images that I have uploaded using the following in my model...
Post.all.each do |ym|
ym.avatar.cache_stored_file!
ym.avatar.retrieve_from_cache!(ym.avatar.cache_name)
ym.avatar.recreate_versions!
ym.save!
end
Unfortunately, I get the following error....
(undefined method `body' for nil:NilClass):
My uploader is named AvatarUploader and is for my Post model. Any advice on how to fix this?
I've ran with a similar problem when using async processing on a read-only server(Heroku). In my case there was a problem when defining file size which I resolved monkey-patching def size from fog file class:
module CarrierWave
module Storage
class Fog < Abstract
class File
def size
file.nil? ? 0 : file.content_length
end
end
end
end
end
I could help you more if the issue still persists and when you post more details from your backtrace and gems configuration.
I'm using Rails 3, Uploadify, to send images to S3.
Right now all the images being upload have the MIME: application/octet-stream
I'd like to fix that but I'm getting the following error:
NoMethodError (undefined method `original_filename' for #<ActiveSupport::HashWithIndifferentAccess:0x107c81998>):
app/models/photo.rb:29:in `upload_file='
app/controllers/photos_controller.rb:15:in `upload'
app/middleware/flash_session_cookie_middleware.rb:14:in `call'
I think this is because all the tutorials out there aren't Rails 3 friendly. Anyone have any ideas? Here's the code:
# Controller
def create
#photo = Photo.new(:upload_file => params[:photo][:image])
...
end
# Model
class Photo < ActiveRecord::Base
require 'mime/types'
...
def upload_file=(data)
data.content_type = MIME::Types.type_for(data.original_filename).to_s
self.image = data
end
end
I'm not familiar with Uploadify, but it seems to be just a javascript generator...
You're passing a params value in as 'data' for #upload_file= . Then you're calling a method (#original_filename) on params[:photo][:image]. Rails is saying that params[:photo][:image] doesn't have such a method.
Is there some kind of File class in 'mime/types'? Should you be creating that File object first?
file = File.new(params[:photo][:image])
and then change that files attribute:
file.content_type = ...
EDIT:
Are you using the paperclip gem? The tutorial that you are using is using paperclip. So in "#asset.file_content_type = MIME::Types.type_for(#asset.original_filename).to_s", I think #asset is an instance of paperclip's File class which does have a #original_filename method. However, I don't see a #file_content_type=() method in the paperclip docs.