Calling save in after_create hook

Scenario:

I’m creating an image file upload service for my web site.

As well as saving the actual file I also need to create a database
record for the file.

I would like to name the file after the record id, but I also need to
save some attributes of the image (width/height/mime_type etc) which I
can’t discover until after the file is created.

The Problem:

  1. The id is not available until after the record is saved so I can’t
    create the file until after the record has been created

  2. if I try to update the record in the after_create hook it creates an
    extra record in the database instead of updating the existing one.

Is this a bug?

Any advice to resolve this problem would be most welcome.

It could be done in the controller of course, but I feel it belongs in
the model.

On Tue, Sep 23, 2008 at 5:31 AM, Noel W. <
[email protected]> wrote:

can’t discover until after the file is created.

The Problem:

  1. The id is not available until after the record is saved so I can’t
    create the file until after the record has been created

Yes, that’s correct that the id of the record isn’t known until it is
saved.

  1. if I try to update the record in the after_create hook it creates an
    extra record in the database instead of updating the existing one.

I think that you would want to use the after_save hook instead of the
after_create if you’re wanting to perform an update of the file’s meta-
data. However, you may also want to take a look at the before_save
callback as well in the api.rubyonrails.com.

Is this a bug?

Where’s the code snippet? Are you trying to store the file into the
database or simply create metadata for the file that’s stored into the
database?

Any advice to resolve this problem would be most welcome.

It could be done in the controller of course, but I feel it belongs in
the model.

Lastly, most of the database reading/writing can be isolated into the
class model and this is the recommended pattern to follow when it’s
possible. However, you should understand the controller’s role in the
MVC design pattern. It’s job is to act as the mediator between the
model and the view. Thus, the controller may make decisions to
create, read, update, and delete (CRUD) a model instance or models
depending on what action is invoked on the controller.

Good luck,

-Conrad

Thanks for the reply, I’ll experiment with the things you sugested.

I’m just trying to save meta data in the database, The file I want to
save on the disk. I’m using the id as a filename (e.g.
mydomain/contents/123.jpg) so that my restful URL will work without
invoking the controller.

Here is my code snippet (forgot to post first time)

require ‘RMagick’
include Magick
class Content < ActiveRecord::Base

def uploaded_file=( file_upload_param )
  self.filename = file_upload_param.original_filename
  @file_upload_param = file_upload_param
end

def after_create
  if ( @file_upload_param )
    # save the uploaded file
    File.open( self.location, "w+" ) do |f|
      f.write( @file_upload_param.read )
    end
    # load the file into an RMagick image list
    il = ImageList.new( self.location )
    self.width = il[0].columns
    self.height = il[0].rows

    self.save # Error: this creates another record in the DB!

    #create the thumbnail
    il[0].crop_resized!( 60, 45 ).write( "#{self.thumb_location}" )
  end
end

def self.location( id, extname )
  "#{RAILS_ROOT}/contents/#{id}.#{extname}"
end

def location
   Content.location( self.id, self.extname )
end

def extname
  File.extname(self.filename)[1..-1].downcase
end

end
#--------------------
I’ll try changing the after_create to after_save and see what happens.

Conrad T. wrote:

On Tue, Sep 23, 2008 at 5:31 AM, Noel W. <
[email protected]> wrote:

can’t discover until after the file is created.

The Problem:

  1. The id is not available until after the record is saved so I can’t
    create the file until after the record has been created

Yes, that’s correct that the id of the record isn’t known until it is
saved.

  1. if I try to update the record in the after_create hook it creates an
    extra record in the database instead of updating the existing one.

I think that you would want to use the after_save hook instead of the
after_create if you’re wanting to perform an update of the file’s meta-
data. However, you may also want to take a look at the before_save
callback as well in the api.rubyonrails.com.

Is this a bug?

Where’s the code snippet? Are you trying to store the file into the
database or simply create metadata for the file that’s stored into the
database?

Any advice to resolve this problem would be most welcome.

It could be done in the controller of course, but I feel it belongs in
the model.

Lastly, most of the database reading/writing can be isolated into the
class model and this is the recommended pattern to follow when it’s
possible. However, you should understand the controller’s role in the
MVC design pattern. It’s job is to act as the mediator between the
model and the view. Thus, the controller may make decisions to
create, read, update, and delete (CRUD) a model instance or models
depending on what action is invoked on the controller.

Good luck,

-Conrad

OK - my bad. All works OK, can’t explain how I made this mistake but it
seems it was working all along.