Niedawno odkurzyłem stary projekt Ruby on Rails. W przeszłości, nigdy nie miałem żadnych problemów z dostaniem wszystkie testy do przekazania, ale teraz jest jeden test, który daje mi następujący błąd:Błąd "Nielegalna mieszanka kolizji" z MySql podczas uruchamiania zestawu testów szyn
ActiveRecord::StatementInvalid: Mysql::Error: #HY000Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=': SELECT * FROM cards WHERE (cards.l1_description = '是' AND cards.l2_word = '')
Więc idę do mojego testu db i zapytać:
mysql> use flashcard_test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show full columns from cards;
+----------------+--------------+-------------------+------+-----+---------+----------------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+----------------+--------------+-------------------+------+-----+---------+----------------+---------------------------------+---------+
| id | int(11) | NULL | NO | PRI | NULL | auto_increment | select,insert,update,references | |
| l2_word | varchar(255) | latin1_swedish_ci | YES | | NULL | | select,insert,update,references | |
| l1_description | text | latin1_swedish_ci | YES | | NULL | | select,insert,update,references | |
| l1_id | int(11) | NULL | YES | | NULL | | select,insert,update,references | |
| l2_id | int(11) | NULL | YES | | NULL | | select,insert,update,references | |
+----------------+--------------+-------------------+------+-----+---------+----------------+---------------------------------+---------+
5 rows in set (0.01 sec)
Jak widać, zestawienie to latin1_swedish_ci, i prawdopodobnie jeśli byłby "utf8_general_ci", moje problemy zostaną rozwiązane. Na szczęście, moja baza rozwój jest już w porządku, więc pójdę i
rake db:test:clone_structure
iz powrotem do MySQL i sprawdź ponownie w db testu
mysql> show full columns from cards;
+----------------+--------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+----------------+--------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
| id | int(11) | NULL | NO | PRI | NULL | auto_increment | select,insert,update,references | |
| l2_word | varchar(255) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
| l1_description | text | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
| l1_id | int(11) | NULL | YES | | NULL | | select,insert,update,references | |
| l2_id | int(11) | NULL | YES | | NULL | | select,insert,update,references | |
+----------------+--------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
5 rows in set (0.00 sec)
Ah, więc teraz wszystko wygląda dobrze, więc po raz kolejny i
rake test
Ale mam ten sam problem na nowo, a kiedy sprawdzić mój test db, uważam, że kolumna sortowania został zresetowany do latin1_swedish_ci.
Nie bardzo rozumiem, jak działa test rake, ale moja robocza hipoteza polega na tym, że odtwarza DB za pomocą schema.rb. Teraz, w jednej z moich migracji, mam teraz
class CreateCards < ActiveRecord::Migration
def self.up
create_table :cards, :options => "DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci" do |t|
t.column :english_word, :string
t.column :chinese_description, :text
end
end
def self.down
drop_table :cards
end
end
A to najwyraźniej zajęło się problemem sortowania. (Mam inną migrację, która odpowiednio zmienia nazwę English_word i Chinese_description na l2_word i l1_description). Jednak ta informacja nie dotarła do schematu.rb. I jakoś, widocznie, MySql zdecydował się założyć, że chcę latin1_swedish_ci.
Podsumowując, myślę, że muszę coś zmodyfikować, żeby użyć zestawu utf8_general_ci, a wtedy moje problemy znikną (prawda?). Ale nie mogę wymyślić, jak zrobić kod, który uruchamia się, gdy "rake test" to zrobić. Czy ktokolwiek może pomóc?
Na co warto, zarówno bazy testowe i rozwojowe zostały stworzone jako
create database flashcard_test default character set utf8 default collate utf8_general_ci;
i
create database flashcard_development default character set utf8 default collate utf8_general_ci;
A moja database.yml ma
development:
adapter: mysql
database: flashcard_development
username: root
password:
encoding: utf8
test:
adapter: mysql
database: flashcard_test
username: root
password:
encoding: utf8
collation: utf8_general_ci
http://nhw.pl/wp/2008/09/16/mysql-collate-setting-in-rails-application zdaje się sugerować że ten problem ma coś wspólnego z połączeniem RoR i MySql, ale nie miałem szczęścia z sugestiami tam.