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.

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

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

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