saving image dimensions with file_column

A minor UI detail in development required that we include the width and height of certain images in the HTML and XML views. Since we were using the file_column plugin, which doesn’t normally save any image information besides the file name, this turned out to require some hacking.

file_column does a great job of making it easy to associate image upload fields with forms, and save the resulting images with a model. You can save various versions as well, manipulated in many ways using Rmagick – a large, small, micro-thumb, for instance, and there are convenient validation hooks. And the plugin, though lightly documented, is simple and easy to understand by reading the code.

And yes attachment_fu is more popular these days, but this system uses active_scaffold, which depends on and is bundled with file_column.

But – file_column does not save the dimensions of the resulting images, a problem for us and at least a few others. Usually, this is not an issue, but in order to optimize the layout of a certain Flash-based UI, we needed to tell Flash via it’s XML setup file the dimensions of the images it was supposed to display.

After various false starts and dead ends, we created the following additions to the plugin that will cause it to save the image height and width to the database, given only columns of the correct name.

Add the following hooks to lib/file_column.rb around line 687, which will cause the model to look for a before_save method in any of it’s subclasses (this mimicks the existing technique used to create the after_save hook and such):

before_save_method = "#{attr}_before_save".to_sym
 
define_method before_save_method do
  instance_variable_set state_attr, send(state_method).before_save
end
 
before_save before_save_method

then, add this method to lib/magick_file_column.rb around line 68. This will look for model methods of the appropriate names, and if found, will read image information from the file on disk and update the model attributes accordingly.

def before_save                                               
  if just_uploaded?                                           
    if @instance.respond_to? "#{@attr}_img_width" or @instance.respond_to? #{@attr}_img_height"                                                               
          img = ::Magick::Image::read(absolute_path).first                       
          if @instance.respond_to? "#{@attr}_img_width="                         
            @instance.send("#{@attr}_img_width=", img.columns)                   
          end                                                                    
          if @instance.respond_to? "#{@attr}_img_height="                        
            @instance.send("#{@attr}_img_height=", img.rows)                     
          end                                                                    
        end                                                                      
      end                                                                        
      self                                                                       
    end

this will cause the plugin to look for a X_img_height and X_img_width method in the model, where X is the base name of your file column.

So, given a basic file_column setup such as

class User < ActiveRecord::Base
  file_column :avatar, :magick => { :geometry => "70x70" }
end

then you can simply add columns named ‘avatar_img_width’ and ‘avatar_img_height’ to your ‘users’ table. The plugin will now automatically save the width and height of the image to those columns.

A migration which would accomplish this might look like:

class AddUserAvatarDimensions < ActiveRecord::Migration
  def self.up
    add_column :users, :avatar_img_width, :int
    add_column :users, :avatar_img_height, :int
  end
 
  def self.down
    remove_column :users, :avatar_img_width
    remove_column :users, :avatar_img_height
  end
end

Known issue: if you use file_column to save multiple sizes of the given image, this will only save the dimensions of the last one. Further work would be needed to include the name attribute of the image size in the column name.

Write a Comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Essentials

A service of Onset Corps LLC, and your humble author and fellow journeyer Samuel Beam.

Wherein, we specialize in over-involved explanations of all types, especially as concerning the efficacious use of tools and processes to maintain simplicity in an irreducibly complex world.

Meta

Pages

Categories