alex
alex

Reputation: 95

Rails model validation with files

I have been stuck on a particular part of my website-to-be for a few days and have been getting quite frustrated. I have code to upload a logo for a user (code below) inside the logo= setter in the user's activerecord model, but this prevents me from using the model's validations. Is there a way for me to rearrange the following code so it is both "pretty" and allows me to use model validations?

Thanks

models/developer.rb

require 'fileutils'

class Developer < ActiveRecord::Base
 has_many :games
 has_many :user_associations
 has_many :users, :through=>:user_associations

 validates_uniqueness_of :name
 validates_length_of :name, :in=>4...16
 #validates_filesize_of :logo, :in=>1.kilobytes..100.kilobytes, :message=>'Logo must be between 1 and 100 kilobytes'

 def logo
   @logo
 end

 def logo=(file)
   errors.add_to_base('Image should be a PNG, JPEG or GIF file') and return if !(['.gif', '.jpg', '.jpeg', '.png'].include? File.extname(file.original_filename).downcase)
  logo_format=File.extname(file.original_filename).downcase
  image_path=RAILS_ROOT+'/logos/'+to_param
  @logo=file.path
  FileUtils.mv(file.path, image_path)
 end

 def self.fetch(id)
   Developer.find_by_name(id.gsub(/_/, ' '))
 end

  def to_param
    return name.gsub(/[ ]/, '_').downcase;
  end

end

controllers/developer_controller.rb (the relevant bits)

class DeveloperController < ApplicationController
  before_filter :load_developer

  def index
   redirect_to :controller=>'developers', :action=>'list' if params[:id].nil?
 end

 def manage
 end

 def set_logo
  if request.post? and !params[:logo].nil?
   @active_developer.logo=params[:logo]
   @write=@active_developer.logo
   @active_developer.save
  end
 end

private

  def load_developer
    if !params[:id].nil?
      @active_developer=Developer.fetch params[:id]
   else
     @active_developer=nil
   end
 end

end

Upvotes: 1

Views: 1127

Answers (2)

Dan Harper
Dan Harper

Reputation: 1130

You may have some of the concepts confused. As tadman mentioned above, an existing plugin is probably the best way to go, attachment_fu is another good one to try. If you do decide to roll your own, you usually:

  • Save the uploaded file to a temp file
  • Remember to have
    :html => { :multipart => true }
    on your form
  • Create an attribute in the model (that's not associated with a database field) to hold the uploaded file data (name/temp file location)
  • Use
    after_validation :save_file_attachment
    (which runs after validation) to move the file to the right location, place the file name into the logo attribute.

Just some ideas, I hope that helps somewhat. Unless this is a learning exercise, go with a plugin :)

Upvotes: 2

tadman
tadman

Reputation: 211590

Instead of rolling your own attachment system, you might want to use a more robust one such as Paperclip which does all of this for you. There are methods to validate the type of file, the size, and many other things, as well as preparing thumbnails for you should that sort of thing be required.

Upvotes: 1

Related Questions