A file-upload suddenly seems to be nil

Hi there,

I posted this issue
https://groups.google.com/forum/?hl=de#!topic/carrierwave/ergk9LaO68kat
the carrierwave-group, but I’m beginning to think this rather is a
rails-issue than a problem with carrierwave. The problem’s this:

I have 2 models, ‘article’ and ‘upload’. article has_many :uploads. In
my
article_controller i have an action named upload:

def upload
@article = Article.find(params[:id])
@article.uploads.create(params[:file])
render :nothing => true
end

this should save a file-upload to article.uploads. I’m using carrierwave
to
save uploads in the upload-model, but that’s probably not the problem.
Before I created the has_many-association I saved the upload directly in
the
article-model using params[:file] in that exact same action and that
worked
great.
Now that I created the association there seems to be a problem with
params[:file]. I keep getting a NoMethodError:

You have a nil object when you didn’t expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.delete

app/controllers/articles_controller.rb:95:in `upload’

where line 95 is @article.uploads.create(params[:file])

if I remove the parameter no errors get thrown. But the console tells me
params[:file] DOES exists and has proper values. Also params[:file]
worked
great before I used the has_many association.

I have no clue what the problem could be.

Can anyone give me a hint?
Thanks,
Lukas

On Fri, Mar 11, 2011 at 4:33 PM, Luke [email protected] wrote:

def upload
Now that I created the association there seems to be a problem with
if I remove the parameter no errors get thrown. But the console tells me
params[:file] DOES exists and has proper values. Also params[:file] worked
great before I used the has_many association.

params[:file] is not the issue. Its the create method you are calling
for
@article.uploads that is throwing the error. In your code, you are
saying
that the create method is part of the upload model, because of your
has_many
association, so it is looking there. Also, since you are doing a
has_many
association between article and upload you will receive back an array.
If
you want to access the method for an object in that array you will need
to
loop over it or call the object in the array directly.

examples:

Loop over the array
@article.uploads.each {|u| u.create(params[:file])}

Call object in array by position
@article.uploads[0].create(params[:file])

Call first object in the arra
@article.uploads.first.create(params[:file])

B.

On Mar 11, 10:33pm, Luke [email protected] wrote:

where line 95 is @article.uploads.create(params[:file])

if I remove the parameter no errors get thrown. But the console tells me
params[:file] DOES exists and has proper values. Also params[:file] worked
great before I used the has_many association.

So what is the value of params[:file] ?

Fred

“file”=>#<ActionDispatch::Http::UploadedFile:0x000001050b4ea0

full parameters:

Parameters: {“name”=>“Screenshot 2011-02-12 um 12.48.33.png”,
“authenticity_token”=>“PUhOOUAHLx+FUnuMI9jY7zwXXxId68v06MbyiImkaSM=”,
“file”=>#<ActionDispatch::Http::UploadedFile:0x000001050b4ea0
@original_filename=“Screenshot 2011-02-12 um 12.48.33.png”,
@content_type=“image/png”, @headers=“Content-Disposition: form-data;
name=“file”; filename=“Screenshot 2011-02-12 um
12.48.33.png”\r\nContent-Type: image/png\r\n”,
@tempfile=#<File:/var/folders/fn/fnhQ4mIBGqO3kQnHeiVzD++++TI/-Tmp-/RackMultipart20110312-5746-19c2n8j>>,
“id”=>“1”}

Hmmm, this does work, at least that error doesn’t occur anymore. But
now
I’m getting the error

Attempt to call private method

where I call create. Also calling create on an instance of an upload
doesn’t
seem right to (n00by) me. Is that the correct way to add a new instance
to
the collection associated with has_many? In the rails getting started
guidehttp://guides.rubyonrails.org/getting_started.html#highlighter_199716
they
do it the way I tried it:

@comment = @post.comments.create(params[:comment])

(Where :comments is a has_many reference in post) but obviously that
didn’t
work. I mean am I getting something wrong? What’s the correct way to
create
and add instances to a has_many association?

On Mar 11, 11:44pm, Luke [email protected] wrote:

“file”=>#<ActionDispatch::Http::UploadedFile:0x000001050b4ea0

So you’re probably passing the wrong thing to foo.uploads.create.
Unless you’ve overridden all sorts of crazy internal active record
stuff, rails is expecting the argument to that create method to be a
hash of attribute names to attribute values, whereas your just giving
it a file.

Fred

Create the upload by calling Upload.create after that you can do
@article.uploads << uploadyoujustcreated that would create the
association
On Mar 11, 2011 5:50 PM, “Frederick C.” [email protected]
wrote:

it a file.

“file”=>#<ActionDispatch::Http::UploadedFile:0x000001050b4ea0
@original_filename=“Screenshot 2011-02-12 um 12.48.33.png”,
@content_type=“image/png”, @headers=“Content-Disposition: form-data;
name="file"; filename="Screenshot 2011-02-12 um
12.48.33.png"\r\nContent-Type: image/png\r\n”,

@tempfile=#<File:/var/folders/fn/fnhQ4mIBGqO3kQnHeiVzD++++TI/-Tmp-/RackMult
ipart20110312-5746-19c2n8j>>,

“id”=>“1”}


You received this message because you are subscribed to the Google G.
“Ruby on Rails: Talk” group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en.

Thanks!

On Mar 12, 1:58pm, Luke [email protected] wrote:

However, I’m wondering how you have to write your constructor to be able to
pass the file when instantiating the model. I mean like this:

@upload = Upload.create(params[:file])

You have to pass a hash of attribute names to values to create - you
can’t just pass a value.
Files are just like any other attribute - you can’t for example do
Person.create(params[:name]), you have to do Person.create(:name =>
params[:name]). In the same way you would do foo.uploads.create :file
=> params[:file]

Fred

That was the problem, thanks a lot! I changed it to

@upload = Upload.new
@upload.file = params[:file]
@upload.save!
@article.uploads << @upload

works like a charm. @upload.file = params[:file] works because I’m using
carrierwave to manage uploads.

However, I’m wondering how you have to write your constructor to be able
to
pass the file when instantiating the model. I mean like this:

@upload = Upload.create(params[:file])

This didn’t work:

def initialize (f)
@file = f
end

Thanks! One last question though, how would the constructor signature
look
for that. Apperently

def initialize(file)

do stuff

end

doesn’t work

On Mar 13, 2:12pm, Luke [email protected] wrote:

Thanks! One last question though, how would the constructor signature look
for that. Apperently

I wouldn’t override the initialiser if I were you. You need to
preserve existing semantics so that (for example) active record can
load your objects from the database. If you really want to, make sure
that you preserve existing calling conventions (ie number of
arguments, pass through the block etc.) and don’t forget to call super

Fred

On Fri, Mar 11, 2011 at 2:33 PM, Luke [email protected] wrote:

def upload
@article = Article.find(params[:id])
@article.uploads.create(params[:file])
render :nothing => true
end

you forgot that you need to pass in key value pairs (as mentioned lower
)

def upload
@article = Article.find(params[:id])
@article.uploads.create(:file => params[:file])
render :nothing => true
end

There is nothing wrong with using create on uploads - it is added to the
collection when you use has many - it in the right way.

you could also do this whole thing in the update action for the article
controller if you simply use ‘fields_for’ inside of a form_for @article
and set ‘accepts_nested_attributes_for :uploads’

then you could do the RESTful way.

def update
@article = Article.find(params[:id])
@article.update_attributes(params[:article])
end


make haste slowly
festina lente \

mobile +1_415_632_6001
[email protected] [email protected]
http://robotarmyma.de