Get Ruby 1.9, Rails, MySQL and UTF-8 to Work Together

By Loren Segal on November 11, 2009 at 116:61:336 PM

Update: You can also try out my fork of mysql-ruby that is properly encoding aware. It doesn't just convert everything to UTF-8, but rather to your default encoding, so make sure to set your LANG!

Here’s a quick little hack to get MySQL 2.8.1 using UTF-8 in Rails 2.3.4 and Ruby 1.9.1.

Filename: lib/mysql_utf8.rb

class Mysql::Result
  def encode(value, encoding = "utf-8")
    String === value ? value.force_encoding(encoding) : value
  end
  
  def each_utf8(&block)
    each_orig do |row|
      yield row.map {|col| encode(col) }
    end
  end
  alias each_orig each
  alias each each_utf8
 
  def each_hash_utf8(&block)
    each_hash_orig do |row|
      row.each {|k, v| row[k] = encode(v) }
      yield(row)
    end
  end
  alias each_hash_orig each_hash
  alias each_hash each_hash_utf8
end

Put that snippet in your Rails project (I used lib/mysql_utf8.rb) and load it in your environment.

That’s all. Now your queries should use Unicode:

$ ./script/console
Loading development environment (Rails 2.3.4)
>> u = User.find(1)
=> #<User id: 1, name: "Test", ...>
>> u.name.encoding
=> #<Encoding:ASCII-8BIT>
>> require 'lib/mysql_utf8'
=> []
>> u = User.find(1)
=> #<User id: 1, name: "Test", ...>
>> u.name.encoding
=> #<Encoding:UTF-8>

Note that if you have BLOB types in MySQL you’ll need to force_encoding back to another type. You could do this in your model.

Questions? Comments? Follow me on Twitter (@lsegal) or email me.