notebook

都内でWEB系エンジニアやってます。

Rails5で複合主キーを扱いたい

Rails5でmigrate時に複合主キーを定義できるようになっていたのでこりゃいいや!とおもって開発してたらupdateできない問題が起きました

migrateスクリプトは以下抜粋

    create_table :summaries, primary_key: ['id', 'date'] do |t|
      t.bigint :id, null: false, auto_increment: true
      t.date :date, null: false
      ....
      ....
      ....

    summaries_statement = "ALTER TABLE summaries
              PARTITION BY RANGE COLUMNS(`date`) (
              PARTITION p201710 VALUES LESS THAN ('2017-11-01') ENGINE = InnoDB,
              PARTITION p201711 VALUES LESS THAN ('2017-12-01') ENGINE = InnoDB,
              PARTITION p201712 VALUES LESS THAN ('2018-01-01') ENGINE = InnoDB,
              PARTITION p201801 VALUES LESS THAN ('2018-02-01') ENGINE = InnoDB,
              PARTITION p201802 VALUES LESS THAN ('2018-03-01') ENGINE = InnoDB,
              PARTITION p201803 VALUES LESS THAN ('2018-04-01') ENGINE = InnoDB,
              PARTITION p201804 VALUES LESS THAN ('2018-05-01') ENGINE = InnoDB,
              PARTITION p201805 VALUES LESS THAN ('2018-06-01') ENGINE = InnoDB,
              PARTITION p201806 VALUES LESS THAN ('2018-07-01') ENGINE = InnoDB
              )
            "
    execute summaries_statement

レポート用のテーブルにパーティションを貼りたくてそのために複合主キーが必要になったためこんな感じでmigrationのスクリプトを書いて実行、 作成まではされていたのでこれはいける!と思って開発を進めていたら

こんなエラーに

Error performing ReportJob (Job ID: 1ab471ba-60d1-4d00-8f43-823c96dec1cc) from Resque(report) in 1625879.14ms: NoMethodError (undefined method `to_sym' for nil:NilClass):
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/sanitization.rb:90:in `block in expand_hash_conditions_for_aggregates'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/sanitization.rb:89:in `each'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/sanitization.rb:89:in `expand_hash_conditions_for_aggregates'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/relation/where_clause_factory.rb:15:in `build'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/relation/query_methods.rb:612:in `where!'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/relation/query_methods.rb:605:in `where'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/relation.rb:79:in `_update_record'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/persistence.rb:575:in `_update_record'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/locking/optimistic.rb:80:in `_update_record'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/attribute_methods/dirty.rb:292:in `_update_record'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/callbacks.rb:344:in `block in _update_record'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:131:in `run_callbacks'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:827:in `_run_update_callbacks'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/callbacks.rb:344:in `_update_record'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/timestamp.rb:107:in `_update_record'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/persistence.rb:563:in `create_or_update'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/callbacks.rb:336:in `block in create_or_update'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:131:in `run_callbacks'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:827:in `_run_save_callbacks'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/callbacks.rb:336:in `create_or_update'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/persistence.rb:162:in `save!'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/validations.rb:50:in `save!'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/attribute_methods/dirty.rb:43:in `save!'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:313:in `block in save!'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:384:in `block in with_transaction_returning_status'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:235:in `block in transaction'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:194:in `block in within_new_transaction'
/home/vagrant/.anyenv/envs/rbenv/versions/2.4.2/lib/ruby/2.4.0/monitor.rb:214:in `mon_synchronize'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:191:in `within_new_transaction'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:235:in `transaction'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:210:in `transaction'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:381:in `with_transaction_returning_status'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:313:in `save!'
/home/vagrant/sample/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.4/lib/active_record/suppressor.rb:46:in `save!'

updateの時しか起こらないっぽい、色々調べた結果composite_primarykeyを使えばOKそうといった結論に至った

該当部分のコードをのぞいて見たけど思いっきりcomposite_primarykeyで書き換えてるっぽい

composite_primary_keys/sanitization.rb at master · composite-primary-keys/composite_primary_keys

github.com

migrationで複合主キー定義できるようになったし普通に使えるんだろうなと思い込んでいたためしょうもないことに時間を使った

どんまい自分