2

在我的应用程序在 Heroku 上并使用 mysql gem 之前。当我将该数据迁移到我自己的 mysql 数据库并切换到 mysql2 gem 时,我的未编码字符以原始 utf8 形式查看。

另一方面,如果我使用 mysql2 gem 将 unicode 数据更新到数据库中,然后切换回 mysql gem,如果我查询 unicode 字符,我会得到问号。

根据我的观察,mysql gem 产生与 mysql 客户端实用程序(在我的 Ubuntu 上)相同的输出,而 mysql2 没有。

有没有办法告诉 mysql2 gem 使用与 mysql 客户端相同的方式读取数据和编码?(因此以同样的方式 mysql gem 做)

4

4 回答 4

3

在将数据迁移到 Heroku 和从 Heroku 迁移数据时,我遇到了类似的问题,您应该能够在 database.yml 中强制编码

encoding: UTF8

还要指出的是 Heroku 默认使用 PostgreSQL,即使你已经包含了 mysql gem。

于 2011-04-18T22:14:40.347 回答
0

好的,我也遇到了很多问题,但是做了一个肮脏的解决方案。问题是,在 Rails 2 中,'mysql' gem 似乎接受来自 mysql 数据库(默认)的 latin1 编码字符串作为 utf 8。

mysql2 不再这样做了。使用 mysql gem 从 rails2 中的 activerecord 加载,显示正确的输出,但在 rails3 中,mysql gem 不再工作。因此,转到 rails2 中的控制台,并使用以下代码段。我使用数据库的副本,以防你想回去。

def update_instance_from_backup(current_instance)
  begin
    ActiveRecord::Base.establish_connection(
      :adapter  => "mysql",
      :host     => "localhost",
      :username => "...",
      :password => "...",
      :database => "database_backup"
    )
    attributes = current_instance.class.find(current_instance.id).attributes
    ActiveRecord::Base.establish_connection(
      :adapter  => "mysql2",
      :host     => "localhost",
      :username => "...",
      :password => "...",
      :database => "database",
      :encoding => "utf8"
    )
  rescue
  else
    current_instance.update_attributes attributes
    puts "#{current_instance.class.name} #{current_instance.id} (dd. #{current_instance.updated_at}) updated"
  end
end

现在,您可以在任何 activerecord 实例上调用 update_instance_from_backup(instance)。

foo = Foo.find(3)
update_instance_from_backup(foo)

将让您更新您的实例数据。你当然可以自己做一个循环。:)

于 2011-05-16T00:12:15.513 回答
0

My solution is to dump the data into a .sql file, use a unicode converter to convert that .sql file to proper encoding and then dump it back to the server.

于 2011-05-19T11:16:49.760 回答
0

I wrote a migration to fix this, as with all things, your mileage may vary.

class FixUnicodeCrap < ActiveRecord::Migration
  def up
    r = ActiveRecord::Base.run_sql(<<sql
select TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, CHARACTER_MAXIMUM_LENGTH, DATA_TYPE from INFORMATION_SCHEMA.COLUMNS 
    where TABLE_SCHEMA = database()
       and DATA_TYPE in ('varchar','text')
       and CHARACTER_SET_NAME = 'latin1'    
sql
)
    r.each do |row|
      target_type = 'BLOB'
      if row[5] == 'varchar'
        target_type = "VARBINARY(#{row[4]})"
      end
      null = row[3] == 'YES' ? "NULL" : "NOT NULL"
      if (row[0] != 'page_views') # if you need to skip any dbs, change this
        execute "ALTER TABLE #{row[0]} MODIFY #{row[1]} #{target_type};"
        execute "ALTER TABLE #{row[0]} MODIFY #{row[1]} #{row[2]} CHARACTER SET utf8 #{null};"
      end
    end
  end

  def down
  end
end


module EasySql
  def self.included(base)
    base.extend(Extensions)
  end

  module Extensions
    def run_sql(sql, *args) 
      connection.execute(
        sanitize_sql_array([sql] + args)
      )
    end
  end
end
ActiveRecord::Base.send :include, EasySql
于 2012-07-03T06:18:05.167 回答