J'ai une application Rails en mode de production, mais tout à coup, cette erreur s'est produite aujourd'hui lorsqu'un utilisateur a essayé de sauvegarder un enregistrement.
Mysql2::Error: Incorrect string value
Plus de détails (du journal de production):
Parameters: {"utf8"=>"â<9c><93>" ...
Mysql2::Error: Incorrect string value: '\xC5\x99\xC3\xA1k
Mysql2::Error: Incorrect string value: '\xC5\x99\xC3\xA1k
Maintenant, j'ai vu certaines solutions nécessitant de supprimer les bases de données et de les recréer, mais je ne peux pas le faire.
Maintenant, mysql montre ceci:
mysql> show variables like 'char%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.04 sec)
Qu'est-ce qui ne va pas et comment puis-je le changer afin que je n'ai aucun problème avec les personnages?
Aussi: est-ce que ce problème peut être résolu avec javascript? Convertissez-le avant de l'envoyer?
Merci
le problème est dû au jeu de caractères de votre côté serveur mysql. Vous pouvez configurer manuellement comme:
ALTER TABLE your_database_name.your_table CONVERT TO CHARACTER SET utf8
ou déposez la table et recréez-la comme ceci:
rake db:drop
rake db:create
rake db:migrate
références:
https://stackoverflow.com/a/18498210/2034097
https://stackoverflow.com/a/16934647/2034097
METTRE &AGRAVE; JOUR
la première commande n'affecte que la table spécifiée, si vous voulez modifier toutes les tables d'une base de données, vous pouvez faire comme
ALTER DATABASE databasename CHARACTER SET utf8 COLLATE utf8_general_ci;
référence:
J'ai réussi à stocker des emojis (qui occupent 4 octets) en suivant ce blog post :
Rails 4, MySQL et Emoji (
Mysql2::Error: Incorrect string value error.
)Vous pourriez penser que vous êtes en sécurité en insérant la plupart des données utf8 dans à mysql lorsque vous avez spécifié que le jeu de caractères est
utf-8
. Malheureusement, Cependant, vous vous trompez. Le problème est que le jeu de caractères utf8 prend 3 octets lorsqu’il est stocké dans une colonne VARCHAR. Caractères Emoji, sur d'autre part, prenez 4 octets.La solution est en 2 parties:
Changez l'encodage de votre table et de vos champs:
ALTER TABLE `[table]` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin, MODIFY [column] VARCHAR(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin
Parlez-en à l'adaptateur
mysql2
:development: adapter: mysql2 database: db username: password: encoding: utf8mb4 collation: utf8mb4_unicode_ci
J'espère que cela aide quelqu'un!
Ensuite, j'ai dû redémarrer mon application et cela a fonctionné ..__ Veuillez noter que certains émojis fonctionneront sans ce correctif, alors que d'autres ne le feront pas:
Vous pouvez utiliser une migration comme celle-ci pour convertir vos tables en utf8:
class ConvertTablesToUtf8 < ActiveRecord::Migration
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_general_ci')
end
dir.down do
change_encoding('latin1','latin1_swedish_ci')
end
end
end
end
Si vous voulez stocker emoji, vous avez besoin de:
1) Créer une migration (merci @mfazekas)
class ConvertTablesToUtf8 < ActiveRecord::Migration
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('utf8mb4','utf8mb4_bin')
end
dir.down do
change_encoding('latin1','latin1_swedish_ci')
end
end
end
end
2) Changez le jeu de caractères de Rails en utf8mb4 (merci @ selvamani-p)
production:
encoding: utf8mb4
Références:
Besoin de changer CHARACTER SET
et COLLATE
pour la base de données déjà créée:
ALTER DATABASE databasename CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Ou il était nécessaire de créer une base de données avec des paramètres prédéfinis:
CREATE DATABASE databasename CHARACTER SET utf8 COLLATE utf8_general_ci;
De plus, si vous ne souhaitez pas modifier la structure de votre base de données, vous pouvez opter pour la sérialisation du champ en question.
class MyModel < ActiveRecord::Base
serialize :content
attr_accessible :content, :title
end
Cela ressemble à un problème d'encodage lors de l'obtention des données de la base de données. Essayez d’ajouter le texte ci-dessous à votre fichier database.yml.
encoding: utf8
J'espère que cela résoudra votre problème
Je viens de découvrir cela et d’apprécier la réponse de @ mfazekas. J'ai apporté deux modifications à la migration: une pour permettre la suppression de connection.current_database (au moins dans Rails 5) et la possibilité de sauter les instructions SQL si vous n'utilisiez pas MySQL (j'utilise toujours SQLite en développement mais j'ai besoin de la migration ).
class ConvertTablesToUtf8 < ActiveRecord::Migration[5.2]
def change_encoding(encoding,collation)
# Allow for different adapter in different environment
return unless ActiveRecord::Base.connection_config[:adapter] == "mysql"
tables = connection.tables
dbname = ActiveRecord::Base.connection_config[: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_general_ci')
end
dir.down do
change_encoding('latin1','latin1_swedish_ci')
end
end
end
end