私には理解できない奇妙な問題があります。
mysql のクラスタリング機能を使用して、関連するレコードをディスク上に並べて保存したいと考えています。テーブルのプライマリ キーによる Mysql クラスタ。デフォルトの Rails モデルの場合は ID です。
ただし、多くのテーブルでは、テーブルの主キーを user_id、subscription_id などにして、それぞれの横にある関連レコードをクラスタ化し、データベースにすべてを要求するときに非常に効率的なルックアップを行うことが理にかなっている場合があります。ユーザーのサブスクリプションの。
これを行うために、次のような mysql テーブルを作成しました。
execute('create table subscriptions (
id integer not null auto_increment,
user_id integer not null,
feed_id integer not null,
folder_id integer,
created_at datetime,
updated_at datetime,
primary key (user_id, feed_id),
key id (id)
) engine=InnoDB default charset=utf8');
私の PK は user_id、feed_id ですが、まだ ID 列が存在していることに注意してください。Rails は、テーブルの PK であると信じているものとしてそれを引き続き使用する必要があります。
まず、設定するまでこれはまったく機能しませんでした:
class Subscription < ActiveRecord::Base
self.primary_key = 'id'
...
end
今、奇妙な部分が来ます。
テストを実行すると、奇妙なエラーが発生します。
Mysql::Error: Field 'id' doesn't have a default value: INSERT INTO `subscriptions`
ただし、アプリケーションを開発モードにして、Web ページから操作を行うと、問題なく動作します。
多くのグーグル検索の後、Rails が MySQL をより厳密なモードに設定するのを止めるモンキー パッチを見つけました。
class ActiveRecord::ConnectionAdapters::MysqlAdapter
private
alias_method :configure_connection_without_strict_mode, :configure_connection
def configure_connection
configure_connection_without_strict_mode
strict_mode = "SQL_MODE=''"
execute("SET #{strict_mode}", :skip_logging)
end
end
これを追加すると、テスト スーツは機能しているように見えますが (すべてではありませんがほとんどのテストで)、作成されたモデルの ID はゼロになります。
再びプロダクション モードでは、Web ページを通じて問題なく動作し、モデルは期待どおり auto_increment ID を取得します。
このセットアップでテスト スイートが正しく動作するように、これを行う方法について何かアイデアを持っている人はいますか?