Forum: Ruby on Rails Error when updating with an image file

Posted by Jean-David (Guest)
on 2012-12-06 10:45
(Received via mailing list)
NOOB ALERT

Now I warned you, here's the problem that's been getting me mad for 
hours

I've got a model for content I'm calling "lead". It has a title, a text 
and
an image used as a background.

I'm not using paperclip or CarrierWave to handle the image file (and I
don't want to, one of my needs here is to learn how this all works).
I'm using this function to upload the file (it comes directly from the
rails guides) :

  def upload
    if params[:lead][:illustration]
      uploaded_io = params[:lead][:illustration]

      File.open(Rails.root.join('app', 'assets', 'images',
uploaded_io.original_filename), 'wb') do |file|
        file.write(uploaded_io.read)
      end

      @lead.illustration = "#{uploaded_io.original_filename}"
    end
  end

When creating a "lead", everything goes fine with create:

  def create
    @lead = Lead.new( params[:lead] )

    upload

    if @lead.save
      flash[:success] = "Lead successfully added."
      redirect_to @lead
    else
      redirect_to root_path
    end
  end

The "lead" gets saved, I can use it. So far, so good.


Now with the problem (remember the NOOB ALERT).
Updating a lead without modifying the image goes fine, but updating with 
a
new image returns this error:

NoMethodError in LeadsController#update

undefined method `name' for nil:NilClass

and

app/controllers/leads_controller.rb:45:in `update'


Here's my update function:

  def update
    @lead = Lead.find_by_id( params[:id] )

    upload

    if @lead.update_attributes!(params[:lead])
      flash[:success] = "Leaderboard successfully updated."
      redirect_to @lead
    else
      render action: "edit"
    end
  end

Basically the same as create. I've been googling and going back and 
forth
for hours and I didn't get to solve this. Any help would be more than
welcome.
Posted by Colin Law (Guest)
on 2012-12-06 11:07
(Received via mailing list)
On 6 December 2012 09:43, Jean-David <jeandavid.cohen@gmail.com> wrote:
> guides) :
>       @lead.illustration = "#{uploaded_io.original_filename}"
>     if @lead.save
> Now with the problem (remember the NOOB ALERT).
> app/controllers/leads_controller.rb:45:in `update'
The error says that you are calling method 'name' for something that
is nil at line 45 in leads_controller.rb.

>       flash[:success] = "Leaderboard successfully updated."
>       redirect_to @lead
>     else
>       render action: "edit"
>     end
>   end
>
> Basically the same as create. I've been googling and going back and forth
> for hours and I didn't get to solve this. Any help would be more than
> welcome.

Unfortunately you have not told us which is line 45.

Colin
Posted by Jean-David (Guest)
on 2012-12-06 11:18
(Received via mailing list)
I supposed it was obvious... ; )

Seriously, line 45 is in the update function:

40   def update
41     @lead = Lead.find_by_id( params[:id] )
42
43    upload
44
45    if @lead.update_attributes!(params[:lead])
46      flash[:success] = "Leaderboard successfully updated."
47      redirect_to @lead
48    else
49      render action: "edit"
50    end
51  end



Le jeudi 6 dcembre 2012 11:05:59 UTC+1, Colin Law a crit :
Posted by Colin Law (Guest)
on 2012-12-06 11:34
(Received via mailing list)
On 6 December 2012 10:16, Jean-David <jeandavid.cohen@gmail.com> wrote:

Please don't top post, it makes it difficult to follow the thread.
Insert you reply inline at appropriate points in the previous message.
 Thanks

> I supposed it was obvious... ; )

Not sure why it would be obvious.

>
> Seriously, line 45 is in the update function:
>
> 40   def update
> 41     @lead = Lead.find_by_id( params[:id] )
> 42
> 43    upload
> 44
> 45    if @lead.update_attributes!(params[:lead])

It is also better not to use html as now the fact that you highlighted
the line above is not visible.
Have you checked that @lead is not nil?
Have a look at the Rails Guide on Debugging to get lots of ideas on
how to debug your code.  Start by looking in log/development.log to
check that the attributes are being passed correctly.  Then, for
example, use the debugger to break into the code and check what is
going on or put diagnostic puts statements in to inspect the data.

Colin
Posted by Colin Law (Guest)
on 2012-12-07 06:28
(Received via mailing list)
On 6 December 2012 12:11, Jean-David <jeandavid.cohen@gmail.com> wrote:
>   @lead.illustration = upload
>
> In "update", this wont work. I need to set:
>   params[:lead][:illustration] = upload
> and the update goes fine.
>
> After finding this out I tried to set
>   params[:lead][:illustration] = upload
> instead of
> @lead.illustration = upload
> in "create", and that wont work.

Can you post your create and update methods as you now have them so I
can see what you are doing.

Colin
Posted by Jean-David (Guest)
on 2012-12-07 07:47
(Received via mailing list)
Le jeudi 6 dcembre 2012 13:23:58 UTC+1, Colin Law a crit :
> >   return "#{uploaded_io.original_filename}"
> > instead of
> > @lead.illustration = upload
> > in "create", and that wont work.
>
> Can you post your create and update methods as you now have them so I
> can see what you are doing.
>

Sure, here goes :

  def create
    @lead = Lead.new( params[:lead] )

    @lead.illustration = upload_image

    if @lead.save
      flash[:success] = "Leaderboard successfully added."
      redirect_to @lead
    else
      redirect_to root_path
    end
  end


  def update
    @lead = Lead.find_by_id( params[:id] )

    params[:lead][:illustration] = upload_image

    if @lead.update_attributes( params[:lead] )
      flash[:success] = "Leaderboard successfully updated."
      redirect_to @lead
    else
      render action: "edit"
    end
  end


  def upload_image
    if params[:lead][:illustration]
      uploaded_io = params[:lead][:illustration]

      File.open(Rails.root.join('app', 'assets', 'images',
uploaded_io.original_filename), 'wb') do |file|
        file.write(uploaded_io.read)
      end

      return "#{uploaded_io.original_filename}"
    end
  end
Posted by Colin Law (Guest)
on 2012-12-07 08:15
(Received via mailing list)
On 6 December 2012 13:43, Jean-David <jeandavid.cohen@gmail.com> wrote:
>> >
>> > After finding this out I tried to set
>
>     end
>   end
>
>
>   def update
>     @lead = Lead.find_by_id( params[:id] )
>
>     params[:lead][:illustration] = upload_image

You said that doing @lead.illustration = upload_image (presumably at
this point) did not work.  It should do, provided that
params[:lead][:illustration] is not present.  If it is then the value
from upload_image will be overwritten by the value from params when
you call  update_attributes.  Another possibility is that if the
illustration is the only field being changed then update_attributes
may not actually save the record (as it does not think anything has
changed).

Probably leaving it as you have it is the simplest solution.

Colin
Posted by Rob Biedenharn (Guest)
on 2012-12-07 10:18
(Received via mailing list)
On Dec 6, 2012, at 9:11 AM, Colin Law wrote:
>>>> "upload" now returns this:
>>>>  params[:lead][:illustration] = upload
>>    @lead = Lead.new( params[:lead] )
>>
> illustration is the only field being changed then update_attributes
> may not actually save the record (as it does not think anything has
> changed).
>
> Probably leaving it as you have it is the simplest solution.
>
> Colin

Jean-David,

Here's a bit of code from an old project of mine:

  def update
    data = params[:product].delete('data') # HashWithIndifferentAccess 
still needs the actual key type to .delete
    begin
      @product = Product.find(params[:id], :conditions => { :virtual => 
true })

      unless data.blank?          # i.e., not replacing image
        content = data.read
        if content.blank?
          flash[:error] = "Selected upload file was empty"
          redirect_to :action => 'edit'
          return
        end
        @product.image_size = ImageSizer.of_blob(content).size
        filename = Product.get_local_image_name data.original_filename
        File.open(File.join(RAILS_ROOT, 'public', filename), 'wb') do 
|f|
          f.write content
        end
        @product.image = filename
      end

      respond_to do |format|
        if @product.update_attributes(params[:product])

  end

Note that I am removing the 'data' key from the attributes hash 
params[:product] so that it isn't used in the .update_attributes call 
later. Perhaps you need to remove the 'illustration' since you've 
already handled that portion of the update.

If you know that the illustration is changed, but ActiveRecord doesn't, 
then perhaps you need to call @lead.illustration_will_change! to inform 
AR that the attribute is dirty and needs to be written out.

-Rob
Posted by Jean-David (Guest)
on 2012-12-07 12:52
(Received via mailing list)
Le jeudi 6 dcembre 2012 17:14:47 UTC+1, Rob Biedenharn a crit :
> >>>>
> >>>> and the update goes fine.
> >> Sure, here goes :
> >>      redirect_to root_path
> > params[:lead][:illustration] is not present.  If it is then the value
> Jean-David,
>       unless data.blank?          # i.e., not replacing image
>         end
> later. Perhaps you need to remove the 'illustration' since you've already
> handled that portion of the update.
>
> If you know that the illustration is changed, but ActiveRecord doesn't,
> then perhaps you need to call @lead.illustration_will_change! to inform AR
> that the attribute is dirty and needs to be written out.
>
> -Rob
>

Thank you Rob, I'll try to put that in my own sauce (that's an 
approximate
translation for french " ma sauce" ; )
Posted by Jean-David (Guest)
on 2012-12-07 12:54
(Received via mailing list)
>
> Colin
>
>
I too guess it should do but I will leave it this way for now.

Thx Colin.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.