Converting Hash to OrderedHash in Serialized ActiveRecord Column
November 1, 2012
Suppose you have an ActiveRecord class like this:
class Report < ActiveRecord::Base
serialize :options, Hashend
And, because you are foolishly still using Ruby 1.8 and doing direct comparisons of the serialized format you need to change it to this:
class Report < ActiveRecord::Base
serialize :options, ActiveSupport::OrderedHash
end
The problem that you face is that the change will cause any existing rows to start throwing `ActiveRecord::SerializationTypeMismatch`. The solution is to run something like this in a migration or console simultaneous with the deploy:
@tables=%w(reports)@tables.each do |table|
puts "============== #{table} =============="
query ="SELECT id,options FROM `#{table}` ORDER BY id"
result = ActiveRecord::Base.connection.execute(query)
result.each do |row|
id = row[0]
hash =YAML.load(row[1])
if hash.is_a?(ActiveSupport::OrderedHash)
puts "Skipping row ##{id} which is already an OrderedHash"else
ordered_hash = ActiveSupport::OrderedHash.new
hash.keys.sort{ |a,b| a.to_s <=> b.to_s }.each do |k|
ordered_hash[k] = hash[k]
end
escaped_options = ActiveRecord::Base.sanitize(ordered_hash.to_yaml)
query ="UPDATE `#{table}` SET options=#{escaped_options} WHERE id=#{id}"
puts "Running "+ query
ActiveRecord::Base.connection.execute query
endend
puts ""end
Converting Hash to OrderedHash in Serialized ActiveRecord Column
Suppose you have an ActiveRecord class like this:
And, because you are foolishly still using Ruby 1.8 and doing direct comparisons of the serialized format you need to change it to this:
The problem that you face is that the change will cause any existing rows to start throwing `ActiveRecord::SerializationTypeMismatch`. The solution is to run something like this in a migration or console simultaneous with the deploy: