views:

369

answers:

3

I have a before_save method that I call that renames an uploaded image.

before_save :randomize_file_name

def randomize_file_name
  extension = File.extname(screen_file_name).downcase
  key = ActiveSupport::SecureRandom.hex(8)
  self.screen.instance_write(:file_name, "#{key}#{extension}")
end

That method is part of my Item model.

That works great when I create a new item or need to update the image associated with an item...but the problem is that if I need to update an item but NOT the image, the randomize_file_name method still gets run and renames the file in the database (though not the file itself, obviously).

So, I'm thinking I need to figure out a way to only run randomize_file_name if a file is included in the form submission...but I'm not sure how to pull that off.

A: 

Just do a quick check at the top of the function and return if you don't need to do anything.

def randomize_file_name
  return unless screen_file_name # or whatever check you need to do
  extension = File.extname(screen_file_name).downcase
  key = ActiveSupport::SecureRandom.hex(8)
  self.screen.instance_write(:file_name, "#{key}#{extension}")
end

Edit after comment:

You can use the dirty object as mentioned by Simone Carletti, or you can get creative.

In the Model:

attr_accessor :some_random_field_name_for_you_to_rename

def randomize_file_name
  return unless some_random_field_name_for_you_to_rename
  extension = File.extname(screen_file_name).downcase
  key = ActiveSupport::SecureRandom.hex(8)
  self.screen.instance_write(:file_name, "#{key}#{extension}")
end

In the form:

<%= f.hidden_field :some_random_field_name_for_you_to_rename, :value => "1" %>
Tony Fontenot
But the problem is that if the form doesn't contain an upload, then it just pulls "screen_file_name" from the database for that ID...I need to specifically check if the form submission includes anything for the image field...and I don't know how to do that from the model.
Shpigford
A: 

go ahead and make your before_save method called on every save but as a first step inside the method you are now having called "before save" you should have an if condition that tests for the specific case you need.

imightbeinatree at Cloudspace
+4  A: 

Use dirty objects.

before_save :randomize_file_name

def randomize_file_name
  # assuming the field that holds the name
  # is called screen_file_name
  if screen_file_name_changed?
    extension = File.extname(screen_file_name).downcase
    key = ActiveSupport::SecureRandom.hex(8)
    self.screen.instance_write(:file_name, "#{key}#{extension}")
  end
end
Simone Carletti
More detailed documentation here: http://apidock.com/rails/ActiveRecord/Dirty
Damien Wilson
This won't get it either. What if the user uploads a new file with the same file name? In this case the file_name will be the same but you may want a different key.
Tony Fontenot