During my last project, I have tried to create a migration that adds a column to a table and then updates that column.
def self.upIf you run that migration, the new column would be added successfully but no data would be updated. Why is that ?!
add_column :file_types, :mime_type, :string
q = FileType.find_by_name('quicktime')
q.update_attributes :mime_type => 'video/quicktime'
end
The problem is that you are trying to update the column, mime_type, immediately after adding it and before allowing the model, FileType, to detect the new changes (strange, I know, but true).
The solution, as documented, is simple. You just need to call
reset_column_information to ensure that the model has the latest column data before the update process.
Here is the code modified:
def self.upAnd here is the code of reset_column_information
add_column :file_types, :mime_type, :string
q = FileType.find_by_name('quicktime')
FileType.reset_column_information
q.update_attributes :mime_type => 'video/quicktime'
end
def reset_column_informationIt simply resets all the cached information about columns, which will cause them to be reloaded on the next request.
read_methods.each { |name| undef_method(name) }
@column_names = @columns = @columns_hash = @content_columns = @dynamic_methods_hash = @read_methods = @inheritance_column = nil
end
Although this problem has a solution, a really worse problem should be mentioned here. In the first case, when you don't call reset_column_information, you don't get any error! The column simply doesn't update. Additionally, if you go back to the previous version and then re-run the migration, surprise, you get no problems and the column updates successfully!
I don't know if this is a reported bug, but it is a strange behavior. However, this won't prevent me from developing more and more Rails applications.
1 comment:
mmm. for optimization issues it should be:
def self.up
add_column :file_types, :mime_type, :string, :default=>'video/quicktime'
FileType.reset_column_information
end
I don't think there was a need to find_by_name the FileTypes. Also, there was no need to iterate on the filetypes as long as the default value was constant and not an evaluated function.
Post a Comment