Giles Bowkett wrote:
> I've got a class which loads files and turns them into ActiveRecord DB
> rows. I'm converting images on a filesystem into blobs in a database.
> 
> class ImageFile < ActiveRecord::Base
>  class << self
>    def import_from_hash(hash)
>      %w{medium square thumb lsquare lthumb tiny}.each do |suffix|
>      filename = "public/item/photos/" + hash[0..2] + "/" + hash +
> "_#{suffix}.jpg"
>        if File.exists?(filename)
>          File.open(filename, "r") do |file|
>            image_file = ImageFile.new
>            eval ("image_file.#{suffix} = file.read")
>          end
>        end
>      end
>    end
>  end
> end
> 
> As you can see the whole thing depends massively on eval(). Yet I
> think it's safe. First, it's only supposed to be run from irb. Second,
> the eval's guarded by an array which essentially acts as a filter. It
> only ever evals code generated by this code and literals from the
> array. (No user input.)
> 
> The suffixes match existing suffixes on the filesystem. They
> correspond to different sizes of the same image. I'm essentially
> refactoring an architecture here. That's why the redundant data in the
> DB. Each image now being represented on the filesystem with
> "xyz_square.jpg" will soon become the square attribute of an ImageFile
> object. This isn't the cleanest design, but it beats the filesystem
> version for my purposes (load-balance-ability and hardware stability).
> 
> Anyway, I think in addition to being safe, this code also shows
> something which would end up **significantly** less concise without
> eval(). It's kind of deliberately Lispy and functional-programmy. I
> would never have written anything like this before reading
> "Higher-Order Perl." I think it's a good example of eval() being
> useful and safe. But, you know, please knock me down (if you see me
> getting high and mighty).
> 

ActiveRecord has the write_attribute and read_attribute methods
which is a better choice for what you are doing. You can also
use [] and []= as aliases for write_attribute and read_attribute

http://ar.rubyonrails.org/classes/ActiveRecord/Base.html

Suffixes = %w{medium square thumb lsquare lthumb tiny}

class ImageFile < ActiveRecord::Base

      def ImageFile.import_from_hash(hash)
         Suffixes.each do |suffix|
             filename =
             "public/item/photos/" + hash[0..2] + "/" + hash + 
"_#{suffix}.jpg"
             if File.exists?(filename)
                 File.open(filename, "r") do |file|
                     image_file = ImageFile.new
		    self[suffix]=file.read
                 end
             end
         end
     end
end


--
Brad Phelan
http://xtargets.com