LoginSignup
12
14

More than 5 years have passed since last update.

Railsアンチパターン<DB編>

Posted at

データベースに関わるアンチパターン

  • 既存のmigrationを勝手に修正する

すでにリポジトリに対してcommitされたupメソッドを編集するべきではない。既存のmigrationを変更してもrake db:migrateコマンドはすでに実行したことがあるタイプスタンプ名のmigrationを適用しないため、混乱が生じる。
基本的にカラムなどの操作は新たにmigrationをまた作成するべきだ。だが、どうしても既存のmigrationを訂正しないといけないということになった場合は、rake db:migrate:redo
commitされたupメソッドを修正するな、混乱の元だ。
もしどうしてもやるんならrake db:migrate:redoで。これは指定ステップ前までのmigrationを取り消し、やり直してくれる。

ちなみにだが、DBのスキーマ管理について、ridgepoleを使うという選択肢もある。これだと冪等性が確保されるので、このような混乱が生じることはない。

  • migration内にRubyコードを入れる。

理論上、up,downメソッドはmigraiton時に実行されるので、こういうことができる(そもそも発想がなかった)

def self.up
  add_column :users, :jobs_count, :integer, :default => 0 
  Users.all.each do |user|
    user.jobs_count = user.jobs.size
    user.save
  end
end

しかしもし使ってるモデル(User)がなくなったらこのmigrationは落ちる。
SQLを直接叩くだと、DBの状態にしか依存しないので少しマシになる。
参考:Railsのmigrationで生SQLを使う+パラメータを使う
もしモデルを参照したい場合はmigrationの中にワンライナークラス定義を含めてしまえばよい。

class Job < ActiveRecord::Base;end
class User < ActiveRecord::Base
has_many :jobs
end

def self.up
  add_column :users, :jobs_count, :integer, :default => 0 User.reset_column_information
  Users.all.each do |user|
    user.jobs_count = user.jobs.size
    user.save
  end
end
  • downメソッドを用意しない

downメソッドがないと、ロールバック時の挙動がコントロールできない。
たとえば、絶対にロールバックしたくないmigrationについてはdownメソッドに例外を仕込んでおくという技がある。こうすると他のメンバーに「このmigrationはロールバックしてはならない」という意図を伝えることができる。

アンチパターン:バリデーション関係

バリデーションをモデル定義にいっぱい書いてる人がいるけど、(今はそれも別クラスに分けられるとはいえ)DBの機能でなんとかできることはそっちの機能を利用したい。が、DBMSによって使える機能が全然違う。
ActiveRecordが提供している機能はだいたいDBMSの最大公約数的な機能だけなので、自分でプラグインを探してくる必要がある。
ここではforeignerが紹介されていたが、Rails4.2では外部キー制約は機能に組み込まれている。たとえば自分はmysqlにunsigned型を追加したのに、mysql-awesomeを利用している。この辺は界隈の情報更新についていく必要がありそう。

12
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
14