Rails: How do I run a before_save only if certain conditions are met?
I have a befo开发者_如何学Cre_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.
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
before_save :randomize_file_name
def randomize_file_name
if screen_file_name
extension = File.extname(screen_file_name).downcase
key = ActiveSupport::SecureRandom.hex(8)
return self.screen.instance_write(:file_name, "#{key}#{extension}") unless !screen_changed?
end
end
This checks only if the file has changed. Works 90% of the time
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.
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" %>
精彩评论