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.
Related
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
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 am using omniauth-facebook and trying to get the profile picture to show up using paperclip. Here is the code I use to get the picture to my User model
def picture_from_url(url)
self.profile_pic =open(url)
end
However, it always saves as stringio.txt. So searching on this behavior I found out that paperclip allows for callbacks so I wrote the following method in the User model to rename the filename
def rename_profile_pic
self.profile_pic.instance_write :filename, "#{self.username}.jpg"
end
and passed it to the callback
before_post_process :rename_profile_pic
But this doesn't seem to help.
Any ideas how i can fix this ?
thanks
In case you haven't found the solution yet:
data = StringIO.new(file_data)
data.class.class_eval { attr_accessor :original_filename, :content_type }
data.content_type = content_type
data.original_filename = file_name
object.attachment = data
Convert your stringio.txt to file using this:
file = StringIO.new(obj)
file.original_filename = "#{self.username}.jpg"
and then assign your file to profile_pic
My solution for creating files from a string:
class FileIO < StringIO
def initialize(content:, filename:)
super(content)
#original_filename = filename
end
attr_reader :original_filename
end
FileIO.new(content: obj, filename: "#{username}.jpg")
This helped me solve the problem with the Carrierwave error when saving the file:
TypeError: no implicit conversion of nil into String
While rendering xml for an object, I am getting the error
NoMethodError (undefined method `model_name' for OrderResponse:Class):
OrderResponse.rb
class OrderResponse
include ActiveModel::Serialization
attr_accessor :payload
end
In controller
def create
#order_response = OrderResponse.new
#order_response.payload = 12345
respond_to do |format|
format.xml { render :xml => #order_response }
end
end
I found other questions with similar titles while searching, according to that i modified 'respond_to' with 'respond_with' which inturns throws an error
undefinedMethod 'model_name' in OrderResponse
How to solve this?
I found an answer to this somewhere on stackoverflow and wish I could credit the source... This is my interpretation of it.
In Rails 3, if you have a resource listed in your routes which has a model .rb file but no active record table behind it, then you'll see this kind of error. This appeared for me as a form_for trying to reference a :controller and :action in this model. Perhaps it is related to Rails attempting to process associations for the model or something similar. Either way, this is new for me since I upgraded an application from Rails 2.3.8.
For me, the appears as:
undefined method `model_name' for SomeModel:Class
To fix it, at the top of the affected class add:
extend ActiveModel::Naming
include ActiveModel::Conversion
def persisted?
false
end
This has worked for me on two models like this.
You could try defining a class method by that name, which returns the name of the class:
def self.model_name; 'OrderResponse'; end
try including ActiveSupport::CoreExtensions::Module where model_name is defined ActiveSupport::CoreExtensions::Module
Is there a better way to save some string as an attachment via Paperlip as making a tmp file, putting the string into it, opening it again and saving it as an attachment ?
Like this :
def save_string data
tmp_file = "/some/path"
File.open(tmp_file,'w') do |f|
f.write(data)
end
File.open(tmp_file,'r') do |f|
ceneo_xml = f
save!
end
end
There is actually a better way - you can wrap it to StringIO which Paperclip enhances and you will get a pseudo uploaded file in no time. You can customize it by defining instance methods or directly create a subclass of StringIO like this
class InvoiceAttachment < StringIO
def initialize(invoice, content)
#invoice = invoice
super(content)
end
def original_filename
from = #invoice.from
to = #invoice.to
date = #invoice.created_at.strftime('%B-%Y').downcase
"invoice_#{date}_from_#{from}_to_#{to}.pdf"
end
def content_type
'application/pdf'
end
end
Enjoy!
Paperclip stores files alongside your models -- this is what it has been written to do, so I think the short answer is "no".
If you look in attachment.rb in the Paperclip source you'll see a method called def assign uploaded_file. If you look at the implementation of this method you can see that it expects the uploaded file object to have a certain methods defined on it.
You could create your own class which followed the same interface as Paperclip expects, but to be honest your solution of saving a file and assigning that to Paperclip is probably the easiest approach.