1

私には理解できない奇妙な問題があります。

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 を取得します。

このセットアップでテスト スイートが正しく動作するように、これを行う方法について何かアイデアを持っている人はいますか?

4

1 に答える 1