I have an ImagesController that kicks off a non-trivial save operation. Here’s the high-level background:
I have several different physical file types to deal with in my application. Each of these belongs_to a Binary. Files can be created, of course, and this process involves uploading a physical file to a temporary location, possibly validating the physical file (for size, type or whatever) and then, assuming no issues, moving the file to a permanent location before creating database records in the appropriate tables (let’s use images and binaries for the purpose of my question).
An Image belongs to a Binary and there’s a BinaryObserver that observes the Image class. In that observer class, there’s a before_create() method that tells the Binary class to upload the image’s physical file and save a related record in the database (with name, path, URI info, etc.).
One of the things that the observer class method does is test for a callback method in the original model, Image in this case. If the method exist and returns false for any reason, then I need for the save operation to fail. I can’t figure out how to do that properly.
In my controller’s create() method, I have:
if @image.save!
flash[:notice] = "Successfully created image."
redirect_to @image
else
flash[:notice] = "Upload failed."
render :action => 'new'
end
I can’t figure out how to trigger the else block. In my BinaryObserver class, I have:
def before_create( model )
binary = Binary.new.upload( model.upload )
if !model.respond_to?( 'before_file_save' ) || model.before_file_save()
binary = binary.store()
model.binary_id = binary.id
model.active = 1
return true
else
# binary.destroy()
File.delete( File.join( Rails.root, binary.path ) )
return false
end
end
At the moment, Image.before_file_save() simply returns false. The physical file is getting deleted, but the save isn’t failing and my controller displays an error message that its show() method can’t find the image (which makes sense since the image wasn’t saved and the physical file was deleted).
How can I force the save operation to fail if the observer class’ before_create() method returns false?
Thanks.
It’s my understanding that using the bang (!) syntax on Model methods will raise an exception if the operation fails. Obviously, the save isn’t failing, but the Observer needs to let your controller know something went wrong. I would follow the same AR way of doing it, with exceptions:
This would mean the observer doesn’t return true, but does raise
YourObserverExceptionif the upload fails (where you arereturning false).