NoMethodError (undefined method `id' for nil:NilClass): in CarrierWave model - ruby-on-rails

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 NoMethodError: undefined method `rails_blob_path` when using active storage

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

Uploader produces errors regarding the column in which it should store the path

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.

Additional fields in CarrierWave Uploader

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

recreate versions - carrierwave-fog-aws

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.

Rails 3 -NoMethodError (undefined method `original_filename

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.

Resources