Ruby on rails 另一种语言中字符的数据类型

Ruby on rails 另一种语言中字符的数据类型,ruby-on-rails,activerecord,sqldatatypes,mysql2,Ruby On Rails,Activerecord,Sqldatatypes,Mysql2,我在activerecord中有一个位置表,其中包含字符串类型列地址。我想把这家花园村餐厅B-B存储在地址列中,我应该使用哪种数据类型? 我已经尝试了textdatatype,但每当我尝试存储它时,都会出现错误: ActiveRecord::StatementInvalid: Mysql2::Error: Incorrect string value: '\xD9\x85\xD8\xB7\xD8\xB9...' for column 'address' 或者,如果有其他方法,我愿意接受建议。您

我在activerecord中有一个
位置
表,其中包含
字符串
类型列
地址
。我想把这家花园村餐厅B-B存储在
地址
列中,我应该使用哪种数据类型?
我已经尝试了
text
datatype,但每当我尝试存储它时,都会出现错误:

ActiveRecord::StatementInvalid: Mysql2::Error: Incorrect string value: '\xD9\x85\xD8\xB7\xD8\xB9...' for column 'address'

或者,如果有其他方法,我愿意接受建议。

您可以在所需的表上运行以下命令:

ALTER TABLE转换为字符集utf8 COLLATE utf8\u unicode\u ci;
还要先从该表中删除所有数据 希望有帮助

生成迁移:(为什么?-不要在数据库上运行自定义查询,因为它们不会记录在模式中)

在生成的迁移中添加如下代码。这将更改数据库的字符集(因此下次迁移将自动遵守新的排序规则),并将更改现有表的字符集

class ChangeCollation < ActiveRecord::Migration[5.0]
  def change_encoding(encoding,collation)
    connection = ActiveRecord::Base.connection
    tables = connection.tables
    dbname =connection.current_database
    execute <<-SQL
      ALTER DATABASE #{dbname} CHARACTER SET #{encoding} COLLATE #{collation};
    SQL
    tables.each do |tablename|
      execute <<-SQL
        ALTER TABLE #{dbname}.#{tablename} CONVERT TO CHARACTER SET #{encoding} COLLATE #{collation};
      SQL
    end
  end

  def change
    reversible do |dir|
      dir.up do
        change_encoding('utf8', 'utf8_unicode_ci')
      end
      dir.down do
        change_encoding('latin1', 'latin1_swedish_ci')
      end
    end
  end
end
在模型中:

class Location < ApplicationRecord
  before_save :encrypt_address
  def encrypt_address
    self.address = ENCRYPTER_CRYPT.encrypt_and_sign(self[:address]) if self[:address].present?
  end

  def address
    # override getter to decrypt and give original urdu string.
    ENCRYPTER_CRYPT.decrypt_and_verify(self[:address]) if self[:address].present?
  end
end
类位置
我不想更改整个activerecord的编码,有没有其他方法可以做到这一点。比如我可以在保存地址之前对其进行编码,然后在从activerecord检索时对其进行解码。从技术上讲,这里根本不涉及activerecord。activerecord只是数据库上的一个关系映射器,将其表示为对象。问题实际上在于数据库的编码。不能对已编码的乌尔都语字符串进行编码并以其他形式保存。这就是为什么,您需要允许数据库和表开始接受该编码。如果存在特定列,您可能要做的是在保存信息之前对其进行加密,并在检索信息时对其进行解密。不确定是否推荐使用。@Touqeer:我添加了一种可能的方法,即在保存到数据库之前以加密方式保存地址,并在检索信息之前重写getter以解密信息。但是,请注意,整个生命周期可能非常昂贵。我不想丢失所有数据。
class ChangeCollation < ActiveRecord::Migration[5.0]
  def change_encoding(encoding,collation)
    connection = ActiveRecord::Base.connection
    tables = connection.tables
    dbname =connection.current_database
    execute <<-SQL
      ALTER DATABASE #{dbname} CHARACTER SET #{encoding} COLLATE #{collation};
    SQL
    tables.each do |tablename|
      execute <<-SQL
        ALTER TABLE #{dbname}.#{tablename} CONVERT TO CHARACTER SET #{encoding} COLLATE #{collation};
      SQL
    end
  end

  def change
    reversible do |dir|
      dir.up do
        change_encoding('utf8', 'utf8_unicode_ci')
      end
      dir.down do
        change_encoding('latin1', 'latin1_swedish_ci')
      end
    end
  end
end
encrypter_key = ActiveSupport::KeyGenerator.new('mypassword').generate_key('a..z', 32)
ENCRYPTER_CRYPT = ActiveSupport::MessageEncryptor.new(encrypter_key)
class Location < ApplicationRecord
  before_save :encrypt_address
  def encrypt_address
    self.address = ENCRYPTER_CRYPT.encrypt_and_sign(self[:address]) if self[:address].present?
  end

  def address
    # override getter to decrypt and give original urdu string.
    ENCRYPTER_CRYPT.decrypt_and_verify(self[:address]) if self[:address].present?
  end
end