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
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.
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])
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.
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:
(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?
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.
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”,
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]
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
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