読者です 読者をやめる 読者になる 読者になる

Rails4でPostgresに生成される主キーや関連キーをbigintegerとする(rails-bigint-pk)

Railsではmigrationを実行したときに特に何も設定を行わない場合、主キーとなるid列はint4となります。ただ、int4は -2,147,483,648から+2,147,483,647 と桁数が小さくデータ量が多い場合やidに欠番が発生する事を前提とする場合などには心許ないことがあります。

数値データ型

そこで、id列にbigintを適用できればすばらしいのにと思うわけですが、これが意外と面倒な作業になります。具体的には以下の2つの作業を行う必要があります。

  1. 作成されるmigrationファイルで対象とするid列をすべてbigintとするように修正する必要がある。
  2. 1で指定したidを参照する列についてもbigintへ修正する。

これらを対象となるidに対してすべて行うとなると結構面倒な作業になります。また、折角Railsが生成してくれるものを手で修正するというのも手間が増えるだけでメリットがありません。

そこで何かよいgemはないかと言うことになりますが、やはり同じようなことを考えている方はいらっしゃいます。

https://github.com/VerticalResponse/rails-bigint-pk

rubygem

rails-bigint-pkというgemが今回の目的に合致していることを確認したのですが、残念ながらRails4.0には対応していませんでした。とはいうものの、利用できないのだろうかと言うことでgithubを確認したところ、やはりRails4へ向けた対応を期待するissueがありました。

Rails4 fixes

ただ、マージされたりする様子はない感じです。折角Rails4への対応を行ったとあるので少し期待しつつfolkしている内容を確認したところ、ばっちりRails4へ対応していました。

https://github.com/caboteria/rails-bigint-pk

branch

とりあえず、WikiにはRails4に対応しているとのことだったのですが、念のためテストを実行します。Rails4ブランチからソースコードをチェックアウトして各データベースをセットアップした後テストを実行します。(rails-bigint-pk はsqlitemysql、postgresの3環境についてテストを行うため、あらかじめインストールとデータベースのセットアップを行う必要があります。

Wikiに記載のあるとおり、 bundle install を実行し、 rake spec でテストを実行します。

[bash] $ bundle install Fetching gem metadata from http://rubygems.org/......... Fetching gem metadata from http://rubygems.org/.. Resolving dependencies... Using rake (10.1.0) Using i18n (0.6.5) Using minitest (4.7.5) Using multi_json (1.8.2) Using atomic (1.1.14) Using thread_safe (0.1.3) Using tzinfo (0.3.38) Installing activesupport (4.0.1) Using builder (3.1.4) Using erubis (2.7.0) Using rack (1.5.2) Using rack-test (0.6.2) Installing actionpack (4.0.1) Using mime-types (1.25) Using polyglot (0.3.3) Using treetop (1.4.15) Using mail (2.5.4) Installing actionmailer (4.0.1) Installing activemodel (4.0.1) Using activerecord-deprecated_finders (1.0.3) Using arel (4.0.1) Installing activerecord (4.0.1) Using bundler (1.3.5) Using timers (1.1.0) Using celluloid (0.15.2) Using coderay (1.1.0) Using columnize (0.3.6) Using debugger-linecache (1.2.0) Using debugger-ruby_core_source (1.2.3) Using debugger (1.6.2) Using diff-lcs (1.2.5) Using ffi (1.9.3) Using formatador (0.2.4) Using rb-fsevent (0.9.3) Using rb-inotify (0.9.2) Using listen (2.2.0) Using lumberjack (1.0.4) Using method_source (0.8.2) Using slop (3.4.7) Using pry (0.9.12.3) Using thor (0.18.1) Using guard (2.2.4) Using guard-bundler (2.0.0) Using guard-ctags-bundler (1.0.1) Using rspec-core (2.14.7) Using rspec-expectations (2.14.4) Using rspec-mocks (2.14.4) Using rspec (2.14.1) Using guard-rspec (4.0.4) Using hashr (0.0.22) Using hike (1.2.3) Using mysql (2.8.1) Using mysql2 (0.3.14) Using pg (0.17.0) Installing railties (4.0.1) Using tilt (1.4.1) Using sprockets (2.10.0) Using sprockets-rails (2.0.1) Installing rails (4.0.1) Using rails-bigint-pk (0.0.2) from source at /Users/ymanabe/rails-bigint-pk2 Using sqlite3 (1.3.8) Using travis-lint (1.7.0) Your bundle is complete! Use bundle show [gemname] to see where a bundled gem is installed. manabe-no-MacBook-Pro:rails-bigint-pk2 ymanabe$ rake spec /Users/ymanabe/.rbenv/versions/2.0.0-p247/bin/ruby -S rspec ./spec/integration/generator_spec.rb ./spec/integration/schema_spec.rb ./spec/migration_spec.rb ./spec/monkey_patch/connection_adapters_spec.rb ..................== ChangeKeysToBigint: migrating ============================================= == ChangeKeysToBigint: migrated (0.0013s) ====================================

.== ChangeKeysToBigint: migrating ============================================= == ChangeKeysToBigint: migrated (0.0012s) ====================================

.== ChangeKeysToBigint: migrating ============================================= == ChangeKeysToBigint: migrated (0.0012s) ====================================

.== ChangeKeysToBigint: migrating ============================================= == ChangeKeysToBigint: migrated (0.0015s) ====================================

.== ChangeKeysToBigint: migrating ============================================= == ChangeKeysToBigint: migrated (0.0012s) ====================================

.== ChangeKeysToBigint: migrating ============================================= == ChangeKeysToBigint: migrated (0.0012s) ====================================

.== ChangeKeysToBigint: migrating ============================================= == ChangeKeysToBigint: migrated (0.0009s) ====================================

.................

Finished in 4 minutes 40.2 seconds 41 examples, 0 failures [/bash]

当初は spec/fixtures のデータベース設定ファイルに設定を忘れたりしたためテストがエラーとなりましたが、正しい値を設定することで問題なくテストをパスできました。

実際の利用方法ですが、こちらもWikiに記載のあるとおりGemファイルに定義を行い、bundle install を実行後 rails generater コマンドでインストールを行います。すると、マイグレーションファイルが作成されるため実行することでid列がint8へ修正されます。

[ruby]

gemはブランチを含めて指定する必要があるので注意

gem 'rails-bigint-pk', git: 'https://github.com/caboteria/rails-bigint-pk.git', :branch => 'rails4' [/ruby]

after_table

適用するタイミングなどは少し調整が必要だと思いますが、これで手間をかけずにid列のデータ型を修正することができます。