Páginas

Saturday, October 1, 2011

Properly show errors with Paperclip and Formtastic

Paperclip has for while now decided that each of its files should have 5 arrays of errors, one for each field it stores in the database (file_name, file_size, content_type and updated_at) and one for the actual file object.

If you are using it alongside with formtastic (or even if you are not), this can be the cause of some problems when trying to show those errors to the client. Therefore, I created a little method to concatenate all these arrays into one.

def properly_show_errors(record)
  @record=record
  if @record.errors.any?
    flash[:error] = []

    @record.errors.each do |attribute,msg|
      if attribute =~ /.+_content_type/ || attribute =~ /.+_content_file_size/
        proper_attribute = attribute.split('_')[0]
        @record.errors.delete_all_at proper_attribute
        @record.errors.add proper_attribute,msg
      end
    end
  end
end  


This takes a record and merges the content_type and content_file_size errors into its own error array. The message can be internationalized in the model to whom the file concerns, as such:

validates_attachment_size :image, :less_than => 1.megabytes, :message => I18n::t('flash.image_size_1mb')

The record is passed on as an instance variable of the caller class. In my use case this caller class is an action in the controller, for instance when creating a page:

@template.properly_show_errors(page)
flash.now[:error] = t("flash.page_not_updated", :name => page.title) 

This will render the page creation form with the error on the flash div, and the record instance variable with page and its errors. The two things of note in this piece of code are the way of using helpers in a controller with the @template variable, and the flash.now that will make the flash message last only one redirect.

Note: This 'bug' has been fixed in formtastic version 1.2.0 and above, but this is still pertinent for those using a prior version